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
4Google Inc.
CHANGELOG+3−0
@@ -0,0 +1,3 @@
12010-05-18 v0.9.0
2 - Initial open source release. Welcome to WebM and VP8!
3
LICENSE+48−0
@@ -0,0 +1,48 @@
1Copyright (c) 2010, Google, Inc.
2
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions
7are 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
21THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33Subject to the terms and conditions of the above License, Google
34hereby grants to You a perpetual, worldwide, non-exclusive,
35no-charge, royalty-free, irrevocable (except as stated in this
36section) patent license to make, have made, use, offer to sell, sell,
37import, and otherwise transfer this implementation of VP8, where such
38license applies only to those patent claims, both currently owned by
39Google and acquired in the future, licensable by Google that are
40necessarily infringed by this implementation of VP8. If You or your
41agent or exclusive licensee institute or order or agree to the
42institution of patent litigation against any entity (including a
43cross-claim or counterclaim in a lawsuit) alleging that this
44implementation of VP8 or any code incorporated within this
45implementation of VP8 constitutes direct or contributory patent
46infringement, or inducement of patent infringement, then any rights
47granted to You under this License for this implementation of VP8
48shall terminate as of the date such litigation is filed.
README+106−0
@@ -0,0 +1,106 @@
1vpx Multi-Format Codec SDK
2README - 19 May 2010
3
4Welcome to the WebM VP8 Codec SDK!
5
6COMPILING 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
103SUPPORT
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__
21extern void die(const char *fmt, ...) __attribute__((noreturn));
22#else
23extern void die(const char *fmt, ...);
24#endif
25
26
27struct 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
39int 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
92const 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
101char **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
111void 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
137unsigned 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
158int 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
179struct vpx_rational
180{
181 int num; /**< fraction numerator */
182 int den; /**< fraction denominator */
183};
184struct 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
15struct 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
24typedef 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
34struct arg arg_init(char **argv);
35int arg_match(struct arg *arg_, const struct arg_def *def, char **argv);
36const char *arg_next(struct arg *arg);
37void arg_show_usage(FILE *fp, const struct arg_def *const *defs);
38char **argv_dup(int argc, const char **argv);
39
40unsigned int arg_parse_uint(const struct arg *arg);
41int arg_parse_int(const struct arg *arg);
42struct vpx_rational arg_parse_rational(const struct arg *arg);
43#endif
build/.gitignore+1−0
@@ -0,0 +1 @@
1x86*-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
2REM Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
3REM
4REM Use of this source code is governed by a BSD-style license and patent
5REM grant that can be found in the LICENSE file in the root of the source
6REM tree. All contributing project authors may be found in the AUTHORS
7REM file in the root of the source tree.
8echo on
9
10
11cl /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
12obj_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 @@
1Microsoft Visual Studio Solution File, Format Version 9.00
2# Visual Studio 2005
3Project("{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
8EndProject
9Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "obj_int_extract", "obj_int_extract.vcproj", "{E1360C65-D375-4335-8057-7ED99CC3F9B2}"
10EndProject
11Project("{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
15EndProject
16Project("{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
21EndProject
22Global
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
88EndGlobal
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
11include config.mk
12quiet?=true
13ifeq ($(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
19all: .DEFAULT
20clean:: .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.
25md5sum := $(firstword $(wildcard \
26 $(foreach e,md5sum openssl,\
27 $(foreach p,$(subst :, ,$(PATH)),$(p)/$(e)*))\
28 ))
29md5sum := $(if $(filter %openssl,$(md5sum)),$(md5sum) dgst -md5,$(md5sum))
30
31TGT_CC:=$(word 3, $(subst -, ,$(TOOLCHAIN)))
32install:
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
58svnstat: ALL_TARGETS:=$(firstword $(ALL_TARGETS))
59endif
60
61ifneq ($(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.
67include $(target)$(if $(FAT_ARCHS),,-$(TOOLCHAIN)).mk
68endif
69BUILD_ROOT?=.
70VPATH=$(SRC_PATH_BARE)
71CFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT) -I$(SRC_PATH)
72ASFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT) -I$(SRC_PATH)
73DIST_DIR?=dist
74HOSTCC?=gcc
75TGT_ISA:=$(word 1, $(subst -, ,$(TOOLCHAIN)))
76TGT_OS:=$(word 2, $(subst -, ,$(TOOLCHAIN)))
77TGT_CC:=$(word 3, $(subst -, ,$(TOOLCHAIN)))
78quiet:=$(if $(verbose),,yes)
79qexec=$(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)
90all-$(target):
91
92.PHONY: clean
93clean::
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
98install:
99.PHONY: install-helper
100install-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
139HAVE_GNU_STRIP := $(if $(CONFIG_DEBUG),,$(HAVE_GNU_STRIP))
140ifeq ($(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 $@ $<
149else
150%.a: %_g.a
151 $(if $(quiet),@echo " [CP] $@ < $<")
152 $(qexec)cp $< $@
153endif
154
155#
156# Rule to extract assembly constants from C sources
157#
158obj_int_extract: build/make/obj_int_extract.c
159 $(if $(quiet),echo " [HOSTCC] $@")
160 $(qexec)$(HOSTCC) -I. -o $@ $<
161CLEAN-OBJS += obj_int_extract
162
163#
164# Utility functions
165#
166pairmap=$(if $(strip $(2)),\
167 $(call $(1),$(word 1,$(2)),$(word 2,$(2)))\
168 $(call pairmap,$(1),$(wordlist 3,$(words $(2)),$(2)))\
169)
170
171enabled=$(filter-out $($(1)-no),$($(1)-yes))
172cond_enabled=$(if $(filter yes,$($(1))), $(call enabled,$(2)))
173
174find_file1=$(word 1,$(wildcard $(subst //,/,$(addsuffix /$(1),$(2)))))
175find_file=$(foreach f,$(1),$(call find_file1,$(strip $(f)),$(strip $(2))) )
176obj_pats=.c=.c.o $(AS_SFX)=$(AS_SFX).o
177objs=$(addprefix $(BUILD_PFX),$(foreach p,$(obj_pats),$(filter %.o,$(1:$(p))) ))
178
179install_map_templates=$(eval $(call install_map_template,$(1),$(2)))
180
181not=$(subst yes,no,$(1))
182
183ifeq ($(CONFIG_MSVS),yes)
184lib_file_name=$(1).lib
185else
186lib_file_name=lib$(1).a
187endif
188#
189# Rule Templates
190#
191define linker_template
192$(1): $(filter-out -%,$(2))
193$(1):
194 $(if $(quiet),@echo " [LD] $$@")
195 $(qexec)$$(LD) $$(strip $$(LDFLAGS) -o $$@ $(2) $(3) $$(extralibs))
196endef
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
205define install_map_template
206$(DIST_DIR)/$(1): $(2)
207 $(if $(quiet),@echo " [INSTALL] $$@")
208 $(qexec)mkdir -p $$(dir $$@)
209 $(qexec)cp -p $$< $$@
210endef
211
212define 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) $$@ $$?
219endef
220
221define lipo_lib_template
222$(1): $(addsuffix /$(1),$(FAT_ARCHS))
223 $(if $(quiet),@echo " [LIPO] $$@")
224 $(qexec)libtool -static -o $$@ $$?
225endef
226
227define lipo_bin_template
228$(1): $(addsuffix /$(1),$(FAT_ARCHS))
229 $(if $(quiet),@echo " [LIPO] $$@")
230 $(qexec)lipo -output $$@ -create $$?
231endef
232
233
234#
235# Get current configuration
236#
237ifneq ($(target),)
238include $(SRC_PATH_BARE)/$(target:-$(TOOLCHAIN)=).mk
239endif
240ifeq ($(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
245endif
246
247#
248# Configuration dependant rules
249#
250$(call pairmap,install_map_templates,$(INSTALL_MAPS))
251
252DOCS=$(call cond_enabled,CONFIG_INSTALL_DOCS,DOCS)
253.docs: $(DOCS)
254 @touch $@
255
256INSTALL-DOCS=$(call cond_enabled,CONFIG_INSTALL_DOCS,INSTALL-DOCS)
257.install-docs: .docs $(addprefix $(DIST_DIR)/,$(INSTALL-DOCS))
258 @touch $@
259
260clean::
261 rm -f .docs .install-docs $(DOCS)
262
263BINS=$(call enabled,BINS)
264.bins: $(BINS)
265 @touch $@
266
267INSTALL-BINS=$(call cond_enabled,CONFIG_INSTALL_BINS,INSTALL-BINS)
268.install-bins: .bins $(addprefix $(DIST_DIR)/,$(INSTALL-BINS))
269 @touch $@
270
271clean::
272 rm -f .bins .install-bins $(BINS)
273
274LIBS=$(call enabled,LIBS)
275.libs: $(LIBS)
276 @touch $@
277$(foreach lib,$(filter %_g.a,$(LIBS)),$(eval $(call archive_template,$(lib))))
278
279INSTALL-LIBS=$(call cond_enabled,CONFIG_INSTALL_LIBS,INSTALL-LIBS)
280.install-libs: .libs $(addprefix $(DIST_DIR)/,$(INSTALL-LIBS))
281 @touch $@
282
283clean::
284 rm -f .libs .install-libs $(LIBS)
285
286ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
287PROJECTS=$(call enabled,PROJECTS)
288.projects: $(PROJECTS)
289 @touch $@
290
291INSTALL-PROJECTS=$(call cond_enabled,CONFIG_INSTALL_PROJECTS,INSTALL-PROJECTS)
292.install-projects: .projects $(addprefix $(DIST_DIR)/,$(INSTALL-PROJECTS))
293 @touch $@
294
295clean::
296 rm -f .projects .install-projects $(PROJECTS)
297endif
298
299# If there are any source files to be installed, then include the build
300# system too.
301ifneq ($(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
317endif
318INSTALL-SRCS := $(call cond_enabled,CONFIG_INSTALL_SRCS,INSTALL-SRCS)
319.install-srcs: $(addprefix $(DIST_DIR)/src/,$(INSTALL-SRCS))
320 @touch $@
321
322clean::
323 rm -f .install-srcs
324
325ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
326 BUILD_TARGETS += .projects
327 INSTALL_TARGETS += .install-projects
328endif
329BUILD_TARGETS += .docs .libs .bins
330INSTALL_TARGETS += .install-docs .install-srcs .install-libs .install-bins
331all-$(target): $(BUILD_TARGETS)
332install: $(INSTALL_TARGETS)
333
334#
335# Development helper targets
336#
337ifneq ($(SRC_PATH_BARE),)
338.PHONY: svnstat
339svnstat:
340 svn stat $(SRC_PATH_BARE)
341endif
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#
19print "@ This file was created from a .asm file\n";
20print "@ using the ads2gas.pl script.\n";
21print "\t.equ DO1STROUNDING, 0\n";
22
23while (<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#
19print "@ This file was created from a .asm file\n";
20print "@ using the ads2gas_apple.pl script.\n\n";
21print "\t.set WIDE_REFERENCE, 0\n";
22print "\t.set ARCHITECTURE, 5\n";
23print "\t.set DO1STROUNDING, 0\n";
24
25my %register_aliases;
26my %macro_aliases;
27
28my @mapping_list = ("\$0", "\$1", "\$2", "\$3", "\$4", "\$5", "\$6", "\$7", "\$8", "\$9");
29
30my @incoming_array;
31
32# Perl trim function to remove whitespace from the start and end of the string
33sub trim($)
34{
35 my $string = shift;
36 $string =~ s/^\s+//;
37 $string =~ s/\s+$//;
38 return $string;
39}
40
41while (<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
12verbose=0
13set -- $*
14for 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
32done
33
34# Absolutize library file names
35for 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"
43done
44for d in $libpaths; do
45 [ -n "$libsearchpath" ] && libsearchpath="${libsearchpath},"
46 libsearchpath="${libsearchpath}$d"
47done
48
49cmd="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#
16die_unknown(){
17 echo "Unknown option \"$1\"."
18 echo "See $0 --help for available options."
19 clean_temp_files
20 exit 1
21}
22
23
24die() {
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
37log(){
38 echo "$@" >>$logfile
39}
40
41
42log_file(){
43 log BEGIN $1
44 pr -n -t $1 >>$logfile
45 log END $1
46}
47
48
49log_echo() {
50 echo "$@"
51 log "$@"
52}
53
54
55fwrite () {
56 outfile=$1
57 shift
58 echo "$@" >> ${outfile}
59}
60
61
62show_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
73Usage: configure [options]
74Options:
75
76Build 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
91Install 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
98EOF
99}
100
101
102show_help_post(){
103 cat <<EOF
104
105
106NOTES:
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
113Supported targets:
114EOF
115 show_targets ${all_platforms}
116 echo
117 exit 1
118}
119
120
121show_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
139show_help() {
140 show_help_pre
141 show_help_post
142}
143
144#
145# List Processing Functions
146#
147set_all(){
148 value=$1
149 shift
150 for var in $*; do
151 eval $var=$value
152 done
153}
154
155
156is_in(){
157 value=$1
158 shift
159 for var in $*; do
160 [ $var = $value ] && return 0
161 done
162 return 1
163}
164
165
166add_cflags() {
167 CFLAGS="${CFLAGS} $@"
168}
169
170
171add_ldflags() {
172 LDFLAGS="${LDFLAGS} $@"
173}
174
175
176add_asflags() {
177 ASFLAGS="${ASFLAGS} $@"
178}
179
180
181add_extralibs() {
182 extralibs="${extralibs} $@"
183}
184
185#
186# Boolean Manipulation Functions
187#
188enable(){
189 set_all yes $*
190}
191
192disable(){
193 set_all no $*
194}
195
196enabled(){
197 eval test "x\$$1" = "xyes"
198}
199
200disabled(){
201 eval test "x\$$1" = "xno"
202}
203
204
205soft_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
214soft_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#
227toupper(){
228 echo "$@" | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
229}
230
231
232tolower(){
233 echo "$@" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz
234}
235
236
237#
238# Temporary File Functions
239#
240source_path=${0%/*}
241enable source_path_used
242if test -z "$source_path" -o "$source_path" = "." ; then
243 source_path="`pwd`"
244 disable source_path_used
245fi
246
247if test ! -z "$TMPDIR" ; then
248 TMPDIRx="${TMPDIR}"
249elif test ! -z "$TEMPDIR" ; then
250 TMPDIRx="${TEMPDIR}"
251else
252 TMPDIRx="/tmp"
253fi
254TMP_H="${TMPDIRx}/vpx-conf-$$-${RANDOM}.h"
255TMP_C="${TMPDIRx}/vpx-conf-$$-${RANDOM}.c"
256TMP_O="${TMPDIRx}/vpx-conf-$$-${RANDOM}.o"
257TMP_X="${TMPDIRx}/vpx-conf-$$-${RANDOM}.x"
258
259clean_temp_files() {
260 rm -f ${TMP_C} ${TMP_H} ${TMP_O} ${TMP_X}
261}
262
263#
264# Toolchain Check Functions
265#
266check_cmd() {
267 log "$@"
268 "$@" >>${logfile} 2>&1
269}
270
271check_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
278check_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
285check_ld() {
286 log check_ld "$@"
287 check_cc $@ \
288 && check_cmd ${LD} ${LDFLAGS} "$@" -o ${TMP_X} ${TMP_O} ${extralibs}
289}
290
291check_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"
299int x;
300EOF
301}
302
303
304check_cflags() {
305 log check_cflags "$@"
306 check_cc "$@" <<EOF
307int x;
308EOF
309}
310
311check_add_cflags() {
312 check_cflags "$@" && add_cflags "$@"
313}
314
315check_add_asflags() {
316 log add_asflags "$@"
317 add_asflags "$@"
318}
319
320check_add_ldflags() {
321 log add_ldflags "$@"
322 add_ldflags "$@"
323}
324
325write_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
336write_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
347true
348}
349
350write_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!
357SRC_PATH="$source_path"
358SRC_PATH_BARE=$source_path
359BUILD_PFX=${BUILD_PFX}
360TOOLCHAIN=${toolchain}
361ASM_CONVERSION=${asm_conversion_cmd:-${source_path}/build/make/ads2gas.pl}
362
363CC=${CC}
364AR=${AR}
365LD=${LD}
366AS=${AS}
367STRIP=${STRIP}
368NM=${NM}
369
370CFLAGS = ${CFLAGS} ${have_config_h}
371ARFLAGS = -rus\$(if \$(quiet),c,v)
372LDFLAGS = ${LDFLAGS}
373ASFLAGS = ${ASFLAGS}
374extralibs = ${extralibs}
375AS_SFX = ${AS_SFX:-.asm}
376EOF
377
378 if enabled rvct; then cat >> $1 << EOF
379fmt_deps = sed -e 's;^__image.axf;\$(dir \$@)\$(notdir \$<).o \$@;' #hide
380EOF
381 else cat >> $1 << EOF
382fmt_deps = sed -e 's;^\(.*\)\.o;\$(dir \$@)\1\$(suffix \$<).o \$@;' #hide
383EOF
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
396write_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}
402EOF
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
410process_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
457process_cmdline() {
458 for opt do
459 optval="${opt#*=}"
460 case "$opt" in
461 *) process_common_cmdline $opt
462 ;;
463 esac
464 done
465}
466
467post_process_cmdline() {
468 true;
469}
470
471setup_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
481process_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';
823EOF
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
842process_toolchain() {
843 process_common_toolchain
844}
845
846print_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
858print_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
872process_targets() {
873 true;
874}
875
876process_detect() {
877 true;
878}
879
880enable logging
881logfile="config.err"
882self=$0
883process() {
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
12self=$0
13show_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}
20die_unknown(){
21 echo "Unknown option \"$1\"."
22 echo "See $0 --help for available options."
23 exit 1
24}
25for 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
40done
41
42[ -n "$srcfile" ] || show_help
43sfx=${sfx:-asm}
44includes=$(egrep -i "include +\"?+[a-z0-9_/]+\.${sfx}" $srcfile |
45 perl -p -e "s;.*?([a-z0-9_/]+.${sfx}).*;\1;")
46#" restore editor state
47for 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
62done
63echo ${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
12self=$0
13self_basename=${self##*/}
14EOL=$'\n'
15
16show_help() {
17 cat <<EOF
18Usage: ${self_basename} [options] file1 [file2 ...]
19
20This script generates a MSVC module definition file containing a list of symbols
21to export from a DLL. Source files are technically bash scripts (and thus may
22use #comment syntax) but in general, take the form of a list of symbols:
23
24 <kind> symbol1 [symbol2, symbol3, ...]
25
26where <kind> is either 'text' or 'data'
27
28
29Options:
30 --help Print this message
31 --out=filename Write output to a file [stdout]
32 --name=project_name Name of the library (required)
33EOF
34 exit 1
35}
36
37die() {
38 echo "${self_basename}: $@"
39 exit 1
40}
41
42die_unknown(){
43 echo "Unknown option \"$1\"."
44 echo "See ${self_basename} --help for available options."
45 exit 1
46}
47
48text() {
49 for sym in "$@"; do
50 echo " $sym" >> ${outfile}
51 done
52}
53
54data() {
55 for sym in "$@"; do
56 printf " %-40s DATA\n" "$sym" >> ${outfile}
57 done
58}
59
60# Process command line
61for 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
74done
75outfile=${outfile:-/dev/stdout}
76[ -n "$name" ] || die "Library name (--name) must be specified!"
77
78echo "LIBRARY ${name}" > ${outfile}
79echo "EXPORTS" >> ${outfile}
80for f in "${file_list[@]}"; do
81 . $f
82done
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
12self=$0
13self_basename=${self##*/}
14EOL=$'\n'
15
16show_help() {
17 cat <<EOF
18Usage: ${self_basename} --name=projname [options] file1 [file2 ...]
19
20This script generates a Visual Studio project file from a list of source
21code files.
22
23Options:
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
38EOF
39 exit 1
40}
41
42die() {
43 echo "${self_basename}: $@" >&2
44 exit 1
45}
46
47die_unknown(){
48 echo "Unknown option \"$1\"." >&2
49 echo "See ${self_basename} --help for available options." >&2
50 exit 1
51}
52
53generate_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
66indent1=" "
67indent=""
68indent_push() {
69 indent="${indent}${indent1}"
70}
71indent_pop() {
72 indent="${indent%${indent1}}"
73}
74
75tag_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
84open_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
98close_tag() {
99 local tag=$1
100 indent_pop
101 echo "${indent}</${tag}>"
102}
103
104tag() {
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
118generate_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
182unset target
183for 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
238done
239outfile=${outfile:-/dev/stdout}
240guid=${guid:-`generate_uuid`}
241asm_use_custom_step=false
242uses_asm=${uses_asm:-false}
243case "${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 ;;
249esac
250
251[ -n "$name" ] || die "Project name (--name) must be specified!"
252[ -n "$target" ] || die "Target (--target) must be specified!"
253
254if ${use_static_runtime:-false}; then
255 release_runtime=0
256 debug_runtime=1
257 lib_sfx=mt
258else
259 release_runtime=2
260 debug_runtime=3
261 lib_sfx=md
262fi
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.
267for 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}"
272done
273
274
275# List Keyword for this target
276case "$target" in
277 x86*)
278 keyword="ManagedCProj"
279 ;;
280 arm*|iwmmx*)
281 keyword="Win32Proj"
282 ;;
283 *) die "Unsupported target $target!"
284esac
285
286# List of all platforms supported for this target
287case "$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!"
306esac
307
308# List Command-line Arguments for this target
309case "$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 ;;
318esac
319
320generate_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
707generate_vcproj |
708 sed -e '/"/s;\([^ "]\)/;\1\\;g' > ${outfile}
709
710exit
711<!--
712TODO: 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
12self=$0
13self_basename=${self##*/}
14EOL=$'\n'
15EOLDOS=$'\r'
16
17show_help() {
18 cat <<EOF
19Usage: ${self_basename} [options] file1 [file2 ...]
20
21This script generates a Visual Studio 2005 solution file from a list of project
22files.
23
24Options:
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
29EOF
30 exit 1
31}
32
33die() {
34 echo "${self_basename}: $@" >&2
35 [ -f "${outfile}" ] && rm -f ${outfile}{,.mk}
36 exit 1
37}
38
39die_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
46indent1=$'\t'
47indent=""
48indent_push() {
49 indent="${indent}${indent1}"
50}
51indent_pop() {
52 indent="${indent%${indent1}}"
53}
54
55parse_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
76process_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
111process_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
163process_makefile() {
164 IFS_bak=${IFS}
165 IFS=$'\r'$'\n'
166 local TAB=$'\t'
167 cat <<EOF
168found_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 \$@
179CLEAN-OBJS += \$(if \$(found_devenv),,.nodevenv.once)
180
181EOF
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
188BUILD_TARGETS += \$(if \$(NO_LAUNCH_DEVENV),,$nows_sln_config)
189clean::
190${TAB}rm -rf "$platform"/"$config"
191.PHONY: $nows_sln_config
192ifneq (\$(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
202else
203$nows_sln_config: $outfile .nodevenv.once
204${TAB}@echo " * Skipping build of $sln_config (devenv.com not in path)."
205${TAB}@echo " * "
206endif
207
208EOF
209 done
210 IFS=${IFS_bak}
211}
212
213# Process command line
214outfile=/dev/stdout
215for 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
249done
250outfile=${outfile:-/dev/stdout}
251mkoutfile=${mkoutfile:-/dev/stdout}
252case "${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 ;;
259esac
260
261for f in "${file_list[@]}"; do
262 parse_project $f
263done
264cat >${outfile} <<EOF
265Microsoft Visual Studio Solution File, Format Version $sln_vers${EOLDOS}
266# $sln_vers_str${EOLDOS}
267EOF
268for proj in ${proj_list}; do
269 process_project $proj >>${outfile}
270done
271process_global >>${outfile}
272process_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
31typedef enum
32{
33 OUTPUT_FMT_PLAIN,
34 OUTPUT_FMT_RVDS,
35 OUTPUT_FMT_GAS,
36} output_fmt_t;
37
38int 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
55int 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;
148bail:
149 return 1;
150
151}
152
153int 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
216bail:
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
237typedef 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
245int 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;
276bail:
277 return 1;
278}
279
280int 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;
298bail:
299 return 1;
300}
301
302char *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
316int 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;
326bail:
327 return 1;
328}
329
330int 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;
455bail:
456 log_msg("Parse error: File does not appear to be valid ELF32\n");
457 return 1;
458}
459
460int 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
530bail:
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
544int 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;
673bail:
674
675 for (i = 0; i < nsections; i++)
676 {
677 free(sectionlist[i]);
678 }
679
680 free(sectionlist);
681
682 return 1;
683}
684
685int 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
752bail:
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
13for opt in "$@"; do
14 optval="${opt#*=}"
15 case "$opt" in
16 --bare) bare=true ;;
17 *) break ;;
18 esac
19 shift
20done
21source_path=${1:-.}
22out_file=${2}
23id=${3:-VERSION_STRING}
24
25git_version_id=""
26if [ -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`
30fi
31
32changelog_version=""
33for 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
39done
40version_str="${changelog_version}${git_version_id}"
41bare_version=${version_str#v}
42major_version=${bare_version%%.*}
43bare_version=${bare_version#*.}
44minor_version=${bare_version%%.*}
45bare_version=${bare_version#*.}
46patch_version=${bare_version%%-*}
47bare_version=${bare_version#${patch_version}}
48extra_version=${bare_version##-}
49
50#since they'll be used as integers below make sure they are or force to 0
51for 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
55done
56
57if [ ${bare} ]; then
58 echo "${changelog_version}${git_version_id}" > $$.tmp
59else
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}"
68EOF
69fi
70if [ -n "$out_file" ]; then
71diff $$.tmp ${out_file} >/dev/null 2>&1 || cat $$.tmp > ${out_file}
72else
73cat $$.tmp
74fi
75rm $$.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\"`"
13source_path=${0%/*}
14. "${source_path}/build/make/configure.sh"
15
16show_help(){
17 show_help_pre
18 cat << EOF
19Advanced 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
40Codecs:
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:
48EOF
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.
74all_platforms="${all_platforms} armv5te-linux-rvct"
75all_platforms="${all_platforms} armv5te-linux-gcc"
76all_platforms="${all_platforms} armv5te-symbian-gcc"
77all_platforms="${all_platforms} armv5te-wince-vs8"
78all_platforms="${all_platforms} armv6-darwin-gcc"
79all_platforms="${all_platforms} armv6-linux-rvct"
80all_platforms="${all_platforms} armv6-linux-gcc"
81all_platforms="${all_platforms} armv6-symbian-gcc"
82all_platforms="${all_platforms} armv6-wince-vs8"
83all_platforms="${all_platforms} iwmmxt-linux-rvct"
84all_platforms="${all_platforms} iwmmxt-linux-gcc"
85all_platforms="${all_platforms} iwmmxt-wince-vs8"
86all_platforms="${all_platforms} iwmmxt2-linux-rvct"
87all_platforms="${all_platforms} iwmmxt2-linux-gcc"
88all_platforms="${all_platforms} iwmmxt2-wince-vs8"
89all_platforms="${all_platforms} armv7-darwin-gcc" #neon Cortex-A8
90all_platforms="${all_platforms} armv7-linux-rvct" #neon Cortex-A8
91all_platforms="${all_platforms} armv7-linux-gcc" #neon Cortex-A8
92all_platforms="${all_platforms} mips32-linux-gcc"
93all_platforms="${all_platforms} ppc32-darwin8-gcc"
94all_platforms="${all_platforms} ppc32-darwin9-gcc"
95all_platforms="${all_platforms} ppc64-darwin8-gcc"
96all_platforms="${all_platforms} ppc64-darwin9-gcc"
97all_platforms="${all_platforms} ppc64-linux-gcc"
98all_platforms="${all_platforms} x86-darwin8-gcc"
99all_platforms="${all_platforms} x86-darwin8-icc"
100all_platforms="${all_platforms} x86-darwin9-gcc"
101all_platforms="${all_platforms} x86-darwin9-icc"
102all_platforms="${all_platforms} x86-linux-gcc"
103all_platforms="${all_platforms} x86-linux-icc"
104all_platforms="${all_platforms} x86-solaris-gcc"
105all_platforms="${all_platforms} x86-win32-gcc"
106all_platforms="${all_platforms} x86-win32-vs7"
107all_platforms="${all_platforms} x86-win32-vs8"
108all_platforms="${all_platforms} x86_64-darwin9-gcc"
109all_platforms="${all_platforms} x86_64-linux-gcc"
110all_platforms="${all_platforms} x86_64-solaris-gcc"
111all_platforms="${all_platforms} x86_64-win64-vs8"
112all_platforms="${all_platforms} universal-darwin8-gcc"
113all_platforms="${all_platforms} universal-darwin9-gcc"
114all_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.
118all_targets="libs examples docs"
119
120# all targets available are enabled, by default.
121for t in ${all_targets}; do
122 [ -f ${source_path}/${t}.mk ] && enable ${t}
123done
124
125# check installed doxygen version
126doxy_version=$(doxygen --version 2>/dev/null)
127doxy_major=${doxy_version%%.*}
128if [ ${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
136fi
137
138# install everything, by default
139enabled doxygen && php -v >/dev/null 2>&1 && enable install_docs
140enable install_bins
141enable install_libs
142enable install_srcs
143
144enable optimizations
145enable fast_unaligned #allow unaligned accesses, if supported by hw
146enable md5
147enable spatial_resampling
148enable multithread
149
150[ -d ${source_path}/../include ] && enable alt_tree_layout
151for d in vp8; do
152 [ -d ${source_path}/${d} ] && disable alt_tree_layout;
153done
154
155if ! enabled alt_tree_layout; then
156# development environment
157[ -d ${source_path}/vp8 ] && CODECS="${CODECS} vp8_encoder vp8_decoder"
158else
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
164fi
165
166CODECS="$(echo ${CODECS} | tr ' ' '\n')"
167CODEC_FAMILIES="$(for c in ${CODECS}; do echo ${c%_*}; done | sort | uniq)"
168
169ARCH_LIST="
170 arm
171 mips
172 x86
173 x86_64
174 ppc32
175 ppc64
176"
177ARCH_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"
194HAVE_LIST="
195 ${ARCH_EXT_LIST}
196 vpx_ports
197 stdint_h
198 alt_tree_layout
199 pthread_h
200 sys_mman_h
201"
202CONFIG_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"
242CMDLINE_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
281process_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
292post_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
320process_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
387process_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"
415int main(void) {return 0;}
416EOF
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
425process_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##
510CONFIGURE_ARGS="$@"
511process "$@"
512cat <<EOF > ${BUILD_PFX}vpx_config.c
513static const char* const cfg = "$CONFIGURE_ARGS";
514const char *vpx_codec_build_config(void) {return cfg;}
515EOF
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
11INSTALL_MAPS += docs/% docs/%
12INSTALL_MAPS += src/% %
13INSTALL_MAPS += % %
14
15# Static documentation authored in doxygen
16CODEC_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
23TXT_DOX-$(CONFIG_VP8) += vp8_api1_migration.dox
24vp8_api1_migration.dox.DESC = VP8 API 1.x Migration
25
26TXT_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
34EXAMPLE_PATH += $(SRC_PATH_BARE) #for CHANGELOG, README, etc
35
36doxyfile: 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
44CLEAN-OBJS += doxyfile $(wildcard docs/html/*)
45docs/html/index.html: doxyfile $(CODEC_DOX) $(TXT_DOX)
46 @echo " [DOXYGEN] $<"
47 @doxygen $<
48DOCS-yes += docs/html/index.html
49
50INSTALL-DOCS-yes = $(wildcard docs/html/*)
51INSTALL-DOCS-$(CONFIG_CODEC_SRCS) += $(addprefix src/,$(CODEC_DOX))
52INSTALL-DOCS-$(CONFIG_CODEC_SRCS) += src/libs.doxy_template
53INSTALL-DOCS-yes += CHANGELOG
54INSTALL-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
24static char *exec_name;
25static int verbose = 0;
26
27static 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
38static 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
63static 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
72void 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
80int 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.
14UTILS-$(CONFIG_DECODERS) += ivfdec.c
15ivfdec.SRCS += md5_utils.c md5_utils.h
16ivfdec.SRCS += vpx_ports/vpx_timer.h
17ivfdec.SRCS += vpx_ports/vpx_integer.h
18ivfdec.SRCS += args.c args.h vpx_ports/config.h
19ivfdec.GUID = BA5FE66F-38DD-E034-F542-B1578C5FB950
20ivfdec.DESCRIPTION = Full featured decoder
21UTILS-$(CONFIG_ENCODERS) += ivfenc.c
22ivfenc.SRCS += args.c args.h vpx_ports/config.h
23ivfenc.SRCS += vpx_ports/mem_ops.h vpx_ports/mem_ops_aligned.h
24ivfenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
25ivfenc.DESCRIPTION = Full featured encoder
26UTILS-$(CONFIG_DECODERS) += example_xma.c
27example_xma.GUID = A955FC4A-73F1-44F7-135E-30D84D32F022
28example_xma.DESCRIPTION = External Memory Allocation mode usage
29
30GEN_EXAMPLES-$(CONFIG_DECODERS) += simple_decoder.c
31simple_decoder.GUID = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC
32simple_decoder.DESCRIPTION = Simplified decoder loop
33GEN_EXAMPLES-$(CONFIG_DECODERS) += postproc.c
34postproc.GUID = 65E33355-F35E-4088-884D-3FD4905881D7
35postproc.DESCRIPTION = Decoder postprocessor control
36GEN_EXAMPLES-$(CONFIG_DECODERS) += decode_to_md5.c
37decode_to_md5.SRCS += md5_utils.h md5_utils.c
38decode_to_md5.GUID = 59120B9B-2735-4BFE-B022-146CA340FE42
39decode_to_md5.DESCRIPTION = Frame by frame MD5 checksum
40
41GEN_EXAMPLES-$(CONFIG_ENCODERS) += simple_encoder.c
42simple_encoder.GUID = 4607D299-8A71-4D2C-9B1D-071899B6FBFD
43simple_encoder.DESCRIPTION = Simplified encoder loop
44GEN_EXAMPLES-$(CONFIG_ENCODERS) += twopass_encoder.c
45twopass_encoder.GUID = 73494FA6-4AF9-4763-8FBB-265C92402FD8
46twopass_encoder.DESCRIPTION = Two-pass encoder loop
47GEN_EXAMPLES-$(CONFIG_ENCODERS) += force_keyframe.c
48force_keyframe.GUID = 3C67CADF-029F-4C86-81F5-D6D4F51177F0
49force_keyframe.DESCRIPTION = Force generation of keyframes
50ifeq ($(CONFIG_DECODERS),yes)
51GEN_EXAMPLES-$(CONFIG_ENCODERS) += decode_with_drops.c
52endif
53decode_with_drops.GUID = CE5C53C4-8DDA-438A-86ED-0DDD3CDB8D26
54decode_with_drops.DESCRIPTION = Drops frames while decoding
55GEN_EXAMPLES-$(CONFIG_ENCODERS) += error_resilient.c
56error_resilient.GUID = DF5837B9-4145-4F92-A031-44E4F832E00C
57error_resilient.DESCRIPTION = Error Resiliency Feature
58
59GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8_scalable_patterns.c
60vp8_scalable_patterns.GUID = 0D6A210B-F482-4D6F-8570-4A9C01ACC88C
61vp8_scalable_patterns.DESCRIPTION = VP8 Scalable Bitstream Patterns
62GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8_set_maps.c
63vp8_set_maps.GUID = ECB2D24D-98B8-4015-A465-A4AF3DCC145F
64vp8_set_maps.DESCRIPTION = VP8 set active and ROI maps
65GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8cx_set_ref.c
66vp8cx_set_ref.GUID = C5E31F7F-96F6-48BD-BD3E-10EBF6E8057A
67vp8cx_set_ref.DESCRIPTION = VP8 set encoder reference frame
68
69
70# Handle extra library flags depending on codec configuration
71CODEC_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.
82ifeq ($(HAVE_ALT_TREE_LAYOUT),yes)
83 LIB_PATH := $(SRC_PATH_BARE)/../lib
84 INC_PATH := $(SRC_PATH_BARE)/../include
85else
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)
93endif
94CFLAGS += $(addprefix -I,$(INC_PATH))
95LDFLAGS += $(addprefix -L,$(LIB_PATH))
96
97
98# Expand list of selected examples to build (as specified above)
99UTILS = $(call enabled,UTILS)
100GEN_EXAMPLES = $(call enabled,GEN_EXAMPLES)
101ALL_EXAMPLES = $(UTILS) $(GEN_EXAMPLES)
102ALL_SRCS = $(foreach ex,$(ALL_EXAMPLES),$($(ex:.c=).SRCS))
103CODEC_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.
122NOT_MSVS = $(if $(CONFIG_MSVS),,yes)
123INSTALL-BINS-$(NOT_MSVS) += $(addprefix bin/,$(ALL_EXAMPLES:.c=))
124INSTALL-SRCS-yes += $(ALL_SRCS)
125OBJS-$(NOT_MSVS) += $(if $(BUILD_OBJS),$(call objs,$(ALL_SRCS)))
126BINS-$(NOT_MSVS) += $(addprefix $(BUILD_PFX),$(ALL_EXAMPLES:.c=))
127
128
129# Instantiate linker template for all examples.
130CODEC_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
143CLEAN-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.
151INSTALL_MAPS += src/%.c %.c
152INSTALL_MAPS += src/% $(SRC_PATH_BARE)/%
153INSTALL_MAPS += bin/% %
154INSTALL_MAPS += % %
155
156
157# Set up additional MSVS environment
158ifeq ($(CONFIG_MSVS),yes)
159CODEC_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.
162VS_PLATFORMS = $(foreach d,$(wildcard */Release/$(CODEC_LIB).lib),$(word 1,$(subst /, ,$(d))))
163INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),bin/$(p)/% $(p)/Release/%)
164endif
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.
173define 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 $$^
184endef
185PROJECTS-$(CONFIG_MSVS) += $(ALL_EXAMPLES:.c=.vcproj)
186INSTALL-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
208samples.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
228CLEAN-OBJS += examples.doxy samples.dox $(ALL_EXAMPLES:.c=.dox)
229DOCS-yes += examples.doxy samples.dox $(ALL_EXAMPLES:.c=.dox)
230examples.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
2Frame-by-frame MD5 Checksum
3===========================
4~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
5This example builds upon the simple decoder loop to show how checksums
6of the decoded output can be generated. These are used for validating
7decoder implementations against the reference implementation, for example.
8~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
9
10MD5 algorithm
11-------------
12The Message-Digest 5 (MD5) is a well known hash function. We have provided
13an implementation derived from the RSA Data Security, Inc. MD5 Message-Digest
14Algorithm for your use. Our implmentation only changes the interface of this
15reference code. You must include the `md5_utils.h` header for access to these
16functions.
17~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
18#include "md5_utils.h"
19~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
20
21
22Processing The Decoded Data
23---------------------------
24Each row of the image is passed to the MD5 accumulator. First the Y plane
25is processed, then U, then V. It is important to honor the image's `stride`
26values.
27~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
28unsigned char md5_sum[16];
29md5_ctx_t md5;
30int i;
31
32md5_init(&md5);
33
34for(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
43md5_finalize(&md5, md5_sum);
44for(i=0; i<16; i++)
45 fprintf(outfile, "%02x",md5_sum[i]);
46fprintf(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
2Decode With Drops Example
3=========================
4~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
5This is an example utility which drops a series of frames, as specified
6on the command line. This is useful for observing the error recovery
7features of the codec.
8~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
9
10Usage
11-----
12This example adds a single argument to the `simple_decoder` example,
13which specifies the range or pattern of frames to drop. The parameter is
14parsed as follows:
15
16~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
17if(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
30Dropping A Range Of Frames
31--------------------------
32To drop a range of frames, specify the starting frame and the ending
33frame to drop, separated by a dash. The following command will drop
34frames 5 through 10 (base 1).
35
36 $ ./decode_with_drops in.ivf out.i420 5-10
37
38
39Dropping A Pattern Of Frames
40----------------------------
41To drop a pattern of frames, specify the number of frames to drop and
42the number of frames after which to repeat the pattern, separated by
43a forward-slash. The following command will drop 3 of 7 frames.
44Specifically, it will decode 4 frames, then drop 3 frames, and then
45repeat.
46
47 $ ./decode_with_drops in.ivf out.i420 3/7
48
49
50Extra Variables
51---------------
52This example maintains the pattern passed on the command line in the
53`n`, `m`, and `is_range` variables:
54
55~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
56int n, m, is_range;
57~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
58
59
60Making The Drop Decision
61------------------------
62The example decides whether to drop the frame based on the current
63frame number, immediately before decoding the frame.
64
65~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE
66if((is_range && frame_cnt >= n && frame_cnt <= m)
67 ||(!is_range && m - (frame_cnt-1)%m <= n)) {
68 putc('X', stdout);
69 continue;
70}
71putc('.', stdout);
72fflush(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
30static unsigned int mem_get_le32(const unsigned char *mem) {
31 return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]);
32}
33
34static 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
46int 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
10static 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
22if(argc!=3)
23 die("Usage: %s <infile> <outfile>\n", argv[0]);
24~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
25
26
27~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
28/* Initialize codec */
29if(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 */
36if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 0))
37 die_codec(&codec, "Failed to decode frame");
38~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECODE
39
40
41~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GET_FRAME
42while((img = vpx_codec_get_frame(&codec, &iter))) {
43~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GET_FRAME
44
45
46~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
47for(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
59if(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
30static void mem_put_le16(char *mem, unsigned int val) {
31 mem[0] = val;
32 mem[1] = val>>8;
33}
34
35static 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
42static 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
54static 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
68static 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
93static 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
110int 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
10static 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
22if(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 */
29res = vpx_codec_enc_config_default(interface, &cfg, 0);
30if(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 */
39cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate
40 / cfg.g_w / cfg.g_h;
41cfg.g_w = width;
42cfg.g_h = height;
43~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG
44
45
46~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INIT
47/* Initialize codec */
48if(vpx_codec_enc_init(&codec, interface, &cfg, 0))
49 die_codec(&codec, "Failed to initialize encoder");
50~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INIT
51
52
53~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME
54frame_avail = read_frame(infile, &raw);
55if(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
62case 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
71if(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
2Error Resiliency Features
3=========================
4~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
5This is an example demonstrating how to enable the error resiliency
6features of the codec.
7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
8
9
10Configuration
11-------------
12Error resiliency is controlled by the g_error_resilient member of the
13configuration structure.
14~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG2
15
16/* Enable error resilient mode */
17cfg.g_error_resilient = 1;
18~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG2
19
20
21Observing The Effects
22---------------------
23Use the `decode_with_drops` example to decode with frames 5-10 dropped.
24Compare the output for a file encoded with this example versus one
25encoded with the `simple_encoder` example.
examples/force_keyframe.txt+28−0
@@ -0,0 +1,28 @@
1@TEMPLATE encoder_tmpl.c
2Forcing A Keyframe
3==================
4~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
5This is an example demonstrating how to control placement of keyframes
6on a frame-by-frame basis.
7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
8
9
10Configuration
11-------------
12Keyframes can be forced by setting the VPX_EFLAG_FORCE_KF bit of the
13flags passed to `vpx_codec_control()`. In this example, we force a
14keyframe every 8 frames.
15
16~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PER_FRAME_CFG
17if(!(frame_cnt & 7))
18 flags |= VPX_EFLAG_FORCE_KF;
19else
20 flags &= ~VPX_EFLAG_FORCE_KF;
21~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PER_FRAME_CFG
22
23
24Observing The Effects
25---------------------
26The output of the encoder examples shows a 'K' rather than a dot '.'
27when the encoder generates a keyframe. Note that every 8 frames a 'K'
28is 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
14self=$0
15
16die_usage() {
17 echo "Usage: $self <example.txt>"
18 exit 1
19}
20
21die() {
22 echo "$@"
23 exit 1
24}
25
26include_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
68txt=$1
69[ -f "$txt" ] || die_usage
70read -r template < "$txt"
71case "$template" in
72 @TEMPLATE*) template=${txt%/*}/${template##@TEMPLATE } ;;
73 *) die "Failed to parse template name from '$template'" ;;
74esac
75
76while 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
84done < "$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
25if(!include_once('includes/PHP-Markdown-Extra-1.2.3/markdown.php'))
26 die("Cannot load Markdown transformer.\n");
27if(!include_once('includes/PHP-SmartyPants-1.5.1e/smartypants.php'))
28 die("Cannot load SmartyPants transformer.\n");
29if(!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';
60while (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
75while (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}
87unset($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]:"";
99print "/*!\\page ".$page_id." ".$page_desc."\n\\htmlonly\n";
100print $page_body;
101print "\\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
116function 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
147function 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
178function 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
14self=$0
15
16die_usage() {
17 echo "Usage: $self <example.txt>"
18 exit 1
19}
20
21die() {
22 echo "$@"
23 exit 1
24}
25
26include_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
48txt=$1
49[ -f "$txt" ] || die_usage
50read -r template < "$txt"
51case "$template" in
52 @TEMPLATE*) template=${txt%/*}/${template##@TEMPLATE } ;;
53 *) die "Failed to parse template name from '$template'" ;;
54esac
55
56fence="~~~~~~~~~"
57fence="${fence}${fence}"
58fence="${fence}${fence}"
59fence="${fence}${fence}"
60while 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
76done < "$txt"
77
78echo
79echo "Putting It All Together"
80echo "======================="
81echo "${fence}"
82${self%/*}/gen_example_code.sh "${txt}"
83echo "${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
58class 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
387class 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
432class 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
2This program is free software; you can redistribute it and/or modify
3it under the terms of the GNU General Public License as published by
4the Free Software Foundation; either version 2 of the License, or (at
5your option) any later version.
6This program is distributed in the hope that it will be useful, but
7WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9(at http://www.gnu.org/copyleft/gpl.html) for more details.*/
10
11function 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}
30function 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 @@
1Revision history for Perl extension HTML::Toc.
2
32001-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
222001-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 @@
1Changes
2Toc.pod
3Toc.pm
4TocGenerator.pm
5TocInsertor.pm
6TocUpdator.pm
7Makefile.PL
8MANIFEST
9t/extend.t
10t/format.t
11t/generate.t
12t/insert.t
13t/manualTest.t
14t/options.t
15t/podExamples.t
16t/propagate.t
17t/siteMap.t
18t/update.t
19t/ManualTest/manualTest1.htm
20t/SiteMap/index.htm
21t/SiteMap/SubDir1/index.htm
22t/SiteMap/SubDir1/SubSubDir1/index.htm
23t/SiteMap/SubDir2/index.htm
24t/SiteMap/SubDir2/SubSubDir1/index.htm
25t/SiteMap/SubDir2/SubSubDir2/index.htm
26t/SiteMap/SubDir3/index.htm
examples/includes/HTML-Toc-0.91/Makefile.PL+8−0
@@ -0,0 +1,8 @@
1use ExtUtils::MakeMaker;
2
3WriteMakefile(
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
5package HTML::Toc;
6
7
8use strict;
9
10
11BEGIN {
12 use vars qw($VERSION);
13
14 $VERSION = '0.91';
15}
16
17
18use constant FILE_FILTER => '.*';
19use constant GROUP_ID_H => 'h';
20use constant LEVEL_1 => 1;
21use constant NUMBERING_STYLE_DECIMAL => 'decimal';
22
23 # Templates
24
25 # Anchor templates
26use constant TEMPLATE_ANCHOR_NAME => '$groupId."-".$node';
27use constant TEMPLATE_ANCHOR_HREF_BEGIN =>
28 '"<a href=#$anchorName>"';
29use constant TEMPLATE_ANCHOR_HREF_BEGIN_FILE =>
30 '"<a href=$file#$anchorName>"';
31use constant TEMPLATE_ANCHOR_HREF_END => '"</a>"';
32use constant TEMPLATE_ANCHOR_NAME_BEGIN =>
33 '"<a name=$anchorName>"';
34use constant TEMPLATE_ANCHOR_NAME_END => '"</a>"';
35use constant TOKEN_UPDATE_BEGIN_OF_ANCHOR_NAME_BEGIN =>
36 '<!-- #BeginTocAnchorNameBegin -->';
37use constant TOKEN_UPDATE_END_OF_ANCHOR_NAME_BEGIN =>
38 '<!-- #EndTocAnchorNameBegin -->';
39use constant TOKEN_UPDATE_BEGIN_OF_ANCHOR_NAME_END =>
40 '<!-- #BeginTocAnchorNameEnd -->';
41use constant TOKEN_UPDATE_END_OF_ANCHOR_NAME_END =>
42 '<!-- #EndTocAnchorNameEnd -->';
43use constant TOKEN_UPDATE_BEGIN_NUMBER =>
44 '<!-- #BeginTocNumber -->';
45use constant TOKEN_UPDATE_END_NUMBER =>
46 '<!-- #EndTocNumber -->';
47use constant TOKEN_UPDATE_BEGIN_TOC =>
48 '<!-- #BeginToc -->';
49use constant TOKEN_UPDATE_END_TOC =>
50 '<!-- #EndToc -->';
51
52use constant TEMPLATE_TOKEN_NUMBER => '"$node &nbsp;"';
53
54 # Level templates
55use constant TEMPLATE_LEVEL => '"<li>$text\n"';
56use constant TEMPLATE_LEVEL_BEGIN => '"<ul>\n"';
57use constant TEMPLATE_LEVEL_END => '"</ul>\n"';
58
59
60END {}
61
62
63#--- HTML::Toc::new() ---------------------------------------------------------
64# function: Constructor
65
66sub 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
100sub _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
161sub _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
185sub _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
287sub _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
329sub _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
383sub 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
398sub 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
418sub 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
541sub setOptions {
542 # Get arguments
543 my ($self, $aOptions) = @_;
544 # Add options
545 %{$self->{options}} = (%{$self->{options}}, %$aOptions);
546} # setOptions()
547
548
5491;
examples/includes/HTML-Toc-0.91/Toc.pod+1710−0
@@ -0,0 +1,1710 @@
1=head1 NAME
2
3HTML::Toc - Generate, insert and update HTML Table of Contents.
4
5=head1 DESCRIPTION
6
7Generate, insert and update HTML Table of Contents.
8
9=head1 Introduction
10
11The HTML::Toc consists out of the following packages:
12
13 HTML::Toc
14 HTML::TocGenerator
15 HTML::TocInsertor
16 HTML::TocUpdator
17
18HTML::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
20HTML::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
61When 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
71Thus 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
81The 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
92For example, with C<index.htm> containing:
93
94 <html>
95 <body>
96 <h1>Chapter</h1>
97 </body>
98 </html>
99
100the 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
111This 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
121For example, with C<index.htm> containing:
122
123 <html>
124 <body>
125 <h1>Chapter</h1>
126 </body>
127 </html>
128
129the 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
143If 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
153When applying the code above on 'index.htm':
154
155 <html>
156 <body>
157 <h1>
158 Chapter
159 </h1>
160 </body>
161 </html>
162
163the output will contain additional update tokens:
164
165 <!-- #BeginToc -->
166 <!-- #EndToc -->
167 <!-- #BeginTocAnchorNameBegin -->
168 <!-- #EndTocAnchorNameBegin -->
169 <!-- #BeginTocAnchorNameEnd -->
170 <!-- #EndTocAnchorNameEnd -->
171
172around 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
188Instead 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
192This 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
202For 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
214the 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
230All 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
234The 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
238The 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
250is formatted.
251
252=head2 Using attribute value as ToC text
253
254Normally, 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
261This 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
277and 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
293Besides 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
297For 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
303and C<doc2.htm>:
304
305 <body>
306 <h1>Chapter of document 2</h1>
307 </body>
308
309Here'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
321And 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
333It'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
339and extend this ToC with text from C<doc2.htm>:
340
341 <body>
342 <h1>Chapter of document 2</h1>
343 </body>
344
345Here'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
358And 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
370It'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
379Here'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
396And 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
423You may want to generate a ToC consisting of multiple ToC groups.
424
425=head3 Specify an additional 'Appendix' group
426
427Suppose 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
438With 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
463the 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
492Suppose 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
503With 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
527the 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
561By 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
565By 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
580For instance with the original file containing:
581
582 <body>
583 <h1>Chapter</h1>
584 <h2>Paragraph</h2>
585 </body>
586
587The 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
598See also: L<Using CSS for ToC formatting|"Using CSS for ToC formatting">.
599
600=head3 Use generated numbers
601
602Instead 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
616For instance with the original file containing:
617
618 <body>
619 <h1>Chapter</h1>
620 <h2>Paragraph</h2>
621 </body>
622
623The 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
634See also: L<Using CSS for ToC formatting|"Using CSS for ToC formatting">.
635
636=head2 Using CSS for ToC formatting
637
638Suppose 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
654Here'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
675Which 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
706Suppose 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
720By 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
769the 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
796Clear the ToC.
797
798=head2 HTML::Toc::format()
799
800 syntax: $scalar = $toc->format()
801 returns: Formatted ToC.
802
803Format 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
812Extend 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
821Extend 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
830Generate 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
840Generate 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
849Insert 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
858Insert 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
867Insert 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
876Insert 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
885Update 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
894Update ToC of specified file. For updator options, see L<HTML::TocUpdator Options|"HTML::TocUpdator Options">.
895
896=head1 Parser Options
897
898When 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
902Available 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
922True (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
930True (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
935Using 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
957the 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
967Each 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
973the 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
983using 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
991Reference 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
999Filename to write output to. If no filename is specified, output will be written to standard output.
1000
1001=head1 HTML::Toc Options
1002
1003The 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
1017The 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
1172Token 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
1179Token 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
1186True (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
1193True (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
1200True (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
1207True (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
1214True (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
1221True (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
1226By 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
1239After specifying:
1240
1241 $toc->setOptions({'doSingleStepLevel' => 0});
1242
1243the 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
1259Specifies 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
1266String to output at end of ToC.
1267
1268=head2 groupId
1269
1270 syntax: $scalar
1271 default: 'h'
1272
1273Sets 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
1289Determines 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
1293This 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
1308String 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
1320Determines 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
1324Examples of valid 'insertionPoint' tokens are:
1325
1326 '<h1>'
1327 '</h1>'
1328 '<!-- ToC -->'
1329 '<!ToC>'
1330 'ToC will be placed here'
1331
1332It 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
1336See also L<tokenBegin|"tokenBegin">.
1337
1338=head2 level
1339
1340 syntax: number
1341 default: 1
1342
1343Number 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
1350Sets the number of spaces each level will be indented, when formatting the ToC.
1351
1352=head2 levelToToc
1353
1354 syntax: <regexp>
1355 default: '.*'
1356
1357Determines 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
1361This 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
1376Determines 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
1387If 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
1394Anchor 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
1401If C<templateAnchorHrefBegin> is a function reference to a function returning the anchor, like in:
1402
1403 $toc->setOptions({'templateAnchorName' => \&assembleAnchorName});
1404
1405the 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
1416Anchor 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
1424If C<templateAnchorHrefBegin> is a function reference to a function returning the anchor, like in:
1425
1426 $toc->setOptions({'templateAnchorHrefBegin' => \&assembleAnchorHrefBegin});
1427
1428the function will be called with the following arguments:
1429
1430 $anchorHrefBegin = &assembleAnchorHrefBegin(
1431 $file, $groupId, $level, $node, $anchorName
1432 );
1433
1434See also: L<templateAnchorName|"templateAnchorName">, L<templateAnchorHrefEnd|"templateAnchorHrefEnd">.
1435
1436=head2 templateAnchorHrefEnd
1437
1438 syntax: <expression|function reference>
1439 default: '"</a>"'
1440
1441Anchor 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
1445the function will be called without arguments:
1446
1447 $anchorHrefEnd = &assembleAnchorHrefEnd;
1448
1449See also: L<templateAnchorHrefBegin|"templateAnchorHrefBegin">.
1450
1451=head2 templateAnchorNameBegin
1452
1453 syntax: <expression|function reference>
1454 default: '"<a name=$anchorName>"'
1455
1456Anchor 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
1464If C<templateAnchorNameBegin> is a function reference to a function returning the anchor name, like in:
1465
1466 $toc->setOptions({'templateAnchorNameBegin' => \&assembleAnchorNameBegin});
1467
1468the function will be called with the following arguments:
1469
1470 $anchorNameBegin = assembleAnchorNameBegin(
1471 $file, $groupId, $level, $node, $anchorName
1472 );
1473
1474See also: L<templateAnchorName|"templateAnchorName">, L<templateAnchorNameEnd|"templateAnchorNameEnd">.
1475
1476=head2 templateAnchorNameEnd
1477
1478 syntax: <expression|function reference>
1479 default: '"</a>"'
1480
1481Anchor 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
1485the function will be called without arguments:
1486
1487 $anchorNameEnd = &assembleAnchorNameEnd;
1488
1489See also: L<templateAnchorNameBegin|"templateAnchorNameBegin">.
1490
1491=head2 templateLevel
1492
1493 syntax: <expression|function reference>
1494 default: '"<li>$text\n"'
1495
1496Expression 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
1504If C<templateLevel> is a function reference to a function returning the ToC node, like in:
1505
1506 $toc->setOptions({'templateLevel' => \&AssembleTocNode});
1507
1508the 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
1519Expression 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
1523which will result in each ToC group being given a class name:
1524
1525 <ul class=toc_h1>
1526 <li>Header
1527 </ul>
1528
1529For 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
1536Expression 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
1540For 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
1547Token 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
1556If C<templateTokenNumber> is a function reference to a function returning the token number, like in:
1557
1558 $toc->setOptions({'templateTokenNumber' => \&assembleTokenNumber});
1559
1560the 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
1575This 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
1583When 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
1587It 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
1591Also, 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
1595See 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
1597See 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
1605The 'tokenEnd' definition applies to the same rules as L<tokenBegin|"tokenBegin">.
1606
1607See 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
1632This 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
1639This 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
1646This 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
1653This 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
1660This 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
1667This 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
1674This 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
1680In 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.
1681When 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
1685HTML::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
1689will go all right, whereas:
1690
1691 <h1><a name=foo>Header</a></h1>
1692
1693will yield the warning:
1694
1695 warning (1): Nested anchor '<a name=foo>' within anchor '<a name=h-1>'.
1696
1697since anchor names aren't allowed to be nested according to the HTML 4.01 specification.
1698
1699=head1 AUTHOR
1700
1701Freddy Vulto E<lt>L<"fvu@fvu.myweb.nl">E<gt>
1702
1703=head1 COPYRIGHT
1704
1705Copyright (c) 2001 Freddy Vulto. All rights reserved.
1706
1707This library is free software; you can redistribute it and/or
1708modify 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
6package HTML::TocGenerator;
7
8
9use strict;
10use HTML::Parser;
11
12
13BEGIN {
14 use vars qw(@ISA $VERSION);
15
16 $VERSION = '0.91';
17
18 @ISA = qw(HTML::Parser);
19}
20
21
22 # Warnings
23use constant WARNING_NESTED_ANCHOR_PS_WITHIN_PS => 1;
24use constant WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS => 2;
25
26
27use constant TOC_TOKEN_ID => 0;
28use constant TOC_TOKEN_INCLUDE => 1;
29use constant TOC_TOKEN_EXCLUDE => 2;
30use constant TOC_TOKEN_TOKENS => 3;
31use constant TOC_TOKEN_GROUP => 4;
32use constant TOC_TOKEN_TOC => 5;
33
34 # Token types
35use constant TT_TAG_BEGIN => 0;
36use constant TT_TAG_END => 1;
37use constant TT_TAG_TYPE_END => 2;
38use constant TT_INCLUDE_ATTRIBUTES_BEGIN => 3;
39use constant TT_EXCLUDE_ATTRIBUTES_BEGIN => 4;
40use constant TT_INCLUDE_ATTRIBUTES_END => 5;
41use constant TT_EXCLUDE_ATTRIBUTES_END => 6;
42use constant TT_GROUP => 7;
43use constant TT_TOC => 8;
44use constant TT_ATTRIBUTES_TOC => 9;
45
46
47use constant CONTAINMENT_INCLUDE => 0;
48use constant CONTAINMENT_EXCLUDE => 1;
49
50use constant TEMPLATE_ANCHOR => '$groupId."-".$node';
51use constant TEMPLATE_ANCHOR_HREF =>
52 '"<a href=#".' . TEMPLATE_ANCHOR . '.">"';
53use constant TEMPLATE_ANCHOR_HREF_FILE =>
54 '"<a href=".$file."#".' . TEMPLATE_ANCHOR . '.">"';
55use constant TEMPLATE_ANCHOR_NAME =>
56 '"<a name=".' . TEMPLATE_ANCHOR . '.">"';
57
58use constant TEMPLATE_TOKEN_NUMBER => '"$node &nbsp"';
59
60
61use constant TT_TOKENTYPE_START => 0;
62use constant TT_TOKENTYPE_END => 1;
63use constant TT_TOKENTYPE_TEXT => 2;
64use constant TT_TOKENTYPE_COMMENT => 3;
65use constant TT_TOKENTYPE_DECLARATION => 4;
66
67
68END {}
69
70
71#--- HTML::TocGenerator::new() ------------------------------------------------
72# function: Constructor
73
74sub 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
95sub _deinitializeBatch() {
96 # Get arguments
97 my ($self) = @_;
98} # _deinitializeBatch()
99
100
101#--- HTML::TocGenerator::_deinitializeExtenderBatch() -------------------------
102
103sub _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
117sub _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
144sub _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
193sub _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
209sub _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
235sub _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
284sub _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
310sub _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
329sub _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
349sub _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
373sub _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
405sub _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
423sub _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
457sub _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
563sub _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
584sub _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
623sub _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
654sub _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
796sub _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
810sub _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
854sub _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
915sub _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
962sub _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
975sub _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
988sub _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
1011sub 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
1021sub 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
1031sub anchorNameEnd {
1032} # anchorNameEnd()
1033
1034
1035#--- HTML::TocGenerator::comment() --------------------------------------------
1036# function: Process comment.
1037# args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
1038
1039sub 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
1062sub 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
1093sub 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
1110sub 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
1128sub 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
1146sub 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
1164sub 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
1174sub 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
1185sub 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
1197sub 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
1217sub 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
1259sub 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
1294package HTML::_TokenTocParser;
1295
1296
1297BEGIN {
1298 use vars qw(@ISA);
1299
1300 @ISA = qw(HTML::Parser);
1301}
1302
1303
1304END {}
1305
1306
1307#--- HTML::_TokenTocParser::new() ---------------------------------------------
1308# function: Constructor
1309
1310sub 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
1332sub _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
1377package HTML::_TokenTocBeginParser;
1378
1379
1380BEGIN {
1381 use vars qw(@ISA);
1382
1383 @ISA = qw(HTML::_TokenTocParser);
1384}
1385
1386END {}
1387
1388
1389#--- HTML::_TokenTocBeginParser::new() ----------------------------------------
1390# function: Constructor
1391
1392sub 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
1411sub _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
1453sub _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
1476sub 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
1489sub 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
1504sub 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
1516sub 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
1527sub 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
1538sub 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
1555sub 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
1569sub 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
1596package HTML::_TokenTocEndParser;
1597
1598
1599BEGIN {
1600 use vars qw(@ISA);
1601
1602 @ISA = qw(HTML::_TokenTocParser);
1603}
1604
1605
1606END {}
1607
1608
1609#--- HTML::_TokenTocEndParser::new() ------------------------------------------
1610# function: Constructor
1611# args: - $aType: Class type.
1612
1613sub 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
1629sub _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
1663sub _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
1678sub 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
1691sub 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
1706sub 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
1720sub 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
1761sub 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
1775sub 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
17931;
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
9package HTML::TocInsertor;
10
11
12use strict;
13use FileHandle;
14use HTML::TocGenerator;
15
16
17BEGIN {
18 use vars qw(@ISA $VERSION);
19
20 $VERSION = '0.91';
21
22 @ISA = qw(HTML::TocGenerator);
23}
24
25 # TocInsertionPoint (TIP) constants
26
27use constant TIP_PREPOSITION_REPLACE => 'replace';
28use constant TIP_PREPOSITION_BEFORE => 'before';
29use constant TIP_PREPOSITION_AFTER => 'after';
30
31use constant TIP_TOKEN_ID => 0;
32use constant TIP_PREPOSITION => 1;
33use constant TIP_INCLUDE_ATTRIBUTES => 2;
34use constant TIP_EXCLUDE_ATTRIBUTES => 3;
35use constant TIP_TOC => 4;
36
37use constant MODE_DO_NOTHING => 0; # 0b00
38use constant MODE_DO_INSERT => 1; # 0b01
39use constant MODE_DO_PROPAGATE => 3; # 0b11
40
41END {}
42
43
44#--- HTML::TocInsertor::new() -------------------------------------------------
45# function: Constructor.
46
47sub 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
67sub _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
84sub _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
124sub _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
156sub _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
195sub _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
222sub _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
249sub _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
298sub _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
356sub 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
369sub _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
421sub _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
463sub _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
499sub _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
540sub _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
569sub _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
583sub 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
597sub 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
624sub 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
638sub 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
666sub 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
692sub 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
718sub 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
737sub 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
753sub 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
768sub 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
796sub 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
845sub 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
872package HTML::_TokenTipParser;
873
874
875BEGIN {
876 use vars qw(@ISA);
877
878 @ISA = qw(HTML::_TokenTocParser);
879}
880
881
882END {}
883
884
885#--- HTML::_TokenTipParser::new() ---------------------------------------------
886# function: Constructor
887
888sub 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
907sub _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
941sub _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
965sub 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
978sub 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
993sub 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
1004sub 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
1015sub 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
1032sub 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
1046sub 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
10661;
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
6package HTML::TocUpdator;
7
8
9use strict;
10use HTML::TocInsertor;
11
12
13BEGIN {
14 use vars qw(@ISA $VERSION);
15
16 $VERSION = '0.91';
17
18 @ISA = qw(HTML::TocInsertor);
19}
20
21
22use constant TUT_TOKENTYPE_START => 0;
23use constant TUT_TOKENTYPE_END => 1;
24use constant TUT_TOKENTYPE_TEXT => 2;
25use constant TUT_TOKENTYPE_COMMENT => 3;
26
27use constant MODE_DO_NOTHING => 0; # 0b00
28use constant MODE_DO_INSERT => 1; # 0b01
29use constant MODE_DO_UPDATE => 3; # 0b11
30
31
32END {}
33
34
35#--- HTML::TocUpdator::new() --------------------------------------------------
36# function: Constructor.
37
38sub 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
61sub _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
86sub _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
125sub _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
164sub _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
179sub _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
215sub _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
245sub _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
265sub _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
285sub _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
301sub _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
318sub 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
340sub 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
361sub 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
414sub 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
444sub 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
458sub 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
471sub 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
497sub 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
524sub 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
544sub _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
562sub 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
576sub 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
591package HTML::_TokenUpdateParser;
592
593
594BEGIN {
595 use vars qw(@ISA);
596
597 @ISA = qw(HTML::Parser);
598}
599
600END {}
601
602
603#--- HTML::_TokenUpdateParser::new() ------------------------------------------
604# function: Constructor
605
606sub 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
622sub 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
635sub 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
647sub 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
664sub 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
685sub 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
6931;
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>
45Better 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>
57Thanks 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
4use strict;
5use Test;
6
7BEGIN { plan tests => 4; }
8
9use HTML::Toc;
10use HTML::TocGenerator;
11
12my ($filename);
13my $toc = HTML::Toc->new;
14my $tocGenerator = HTML::TocGenerator->new;
15
16$toc->setOptions({
17 'doLinkToToken' => 0,
18 'levelIndent' => 0,
19 'header' => '',
20 'footer' => '',
21});
22
23
24BEGIN {
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>
31EOT
32 close(FILE);
33}
34
35
36END {
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
49ok($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
59ok($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
69ok($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
82ok($toc->format() . "\n", <<'EOT');
83<ul>
84<li><a href=#h-1>Header</a>
85<li><a href=#h-2>Header</a>
86</ul>
87EOT
examples/includes/HTML-Toc-0.91/t/format.t+157−0
@@ -0,0 +1,157 @@
1#--- format.t -----------------------------------------------------------------
2# function: Test ToC formatting.
3
4use strict;
5use Test;
6
7BEGIN { plan tests => 6; }
8
9use HTML::Toc;
10use HTML::TocGenerator;
11use HTML::TocInsertor;
12
13my ($output, $content, $filename);
14my $toc = HTML::Toc->new;
15my $tocGenerator = HTML::TocGenerator->new;
16my $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
27BEGIN {
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>
34EOT
35}
36
37
38END {
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});
50ok($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'});
58ok($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'});
76ok($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});
91ok("$output\n", <<EOT);
92<!-- TocHeader --><ul>
93<li>Header1
94</ul><!-- TocFooter --><h1>Header1</h1>
95EOT
96
97
98 # Test 'doSingleStepLevel' => 1
99TestSingleStepLevel1();
100 # Test 'doSingleStepLevel' => 0
101TestSingleStepLevel0();
102
103
104#--- 5. TestSingleStepLevel1 --------------------------------------------------
105
106sub 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>
114EOT
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 -->
128EOT
129} # TestSingleStepLevel1()
130
131
132#--- 6. TestSingleStepLevel0 --------------------------------------------------
133
134sub 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>
144EOT
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 -->
156EOT
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
4use strict;
5use Test;
6
7BEGIN { plan tests => 13; }
8
9use HTML::Toc;
10use HTML::TocGenerator;
11
12my ($filename);
13my $toc = HTML::Toc->new;
14my $tocGenerator = HTML::TocGenerator->new;
15
16$toc->setOptions({
17 'doLinkToToken' => 0,
18 'levelIndent' => 0,
19 'header' => '',
20 'footer' => '',
21});
22
23
24BEGIN {
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>
31EOT
32 close(FILE);
33}
34
35
36END {
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>");
45ok($toc->format(), "<ul>\n<li>Header\n</ul>");
46
47
48#--- 2. generateFromFile ------------------------------------------------------
49
50$tocGenerator->generateFromFile($toc, $filename);
51ok($toc->format(), "<ul>\n<li>Header\n</ul>");
52
53
54#--- 3. generateFromFiles -----------------------------------------------------
55
56$tocGenerator->generateFromFile($toc, [$filename, $filename]);
57ok($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});
64ok($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);
71ok($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
81ok($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
88sub 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
101ok($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>");
110ok($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>");
121ok($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>");
132ok($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>");
144ok($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);
165ok($toc->format() . "\n", <<'EOT');
166<ul>
167<li>Header1
168<ul>
169<li>Appendix
170</ul>
171</ul>
172EOT
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);
193ok($toc->format() . "\n", <<'EOT');
194<ul>
195<li>Header1
196</ul>
197<ul>
198<li>Appendix
199</ul>
200EOT
examples/includes/HTML-Toc-0.91/t/insert.t+336−0
@@ -0,0 +1,336 @@
1#--- insert.t -----------------------------------------------------------------
2# function: Test ToC insertion.
3
4use strict;
5use Test;
6
7BEGIN { plan tests => 10; }
8
9use HTML::Toc;
10use HTML::TocGenerator;
11use HTML::TocInsertor;
12
13my ($output, $content, $filename);
14my $toc = HTML::Toc->new;
15my $tocGenerator = HTML::TocGenerator->new;
16my $tocInsertor = HTML::TocInsertor->new;
17
18$toc->setOptions({
19 'doLinkToToken' => 0,
20 'levelIndent' => 0,
21 'header' => "",
22 'footer' => "",
23});
24
25
26BEGIN {
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>
33EOT
34}
35
36
37END {
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
53ok($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
66ok($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
79ok($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
92ok($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
106open(FILE, "<$filename") || die "Can't open $filename: $!";
107$content = join('', <FILE>);
108close(FILE);
109 # Test ToC
110ok($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});
120ok($output, "");
121
122
123#--- TestAfterDeclaration() ---------------------------------------------------
124# function: Test putting HTML comment after declaration.
125
126sub 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>
144EOT
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>
166EOT
167} # TestAfterDeclaration()
168
169
170#--- TestNumberingStyle() -----------------------------------------------------
171# function: Test numberingstyle.
172
173sub 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>
204EOT
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>
228EOT
229} # TestNumberingStyle()
230
231
232#--- TestReplaceComment() -----------------------------------------------------
233# function: Test replacing HTML comment with ToC.
234
235sub 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>
254EOT
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>
277EOT
278} # TestReplaceComment()
279
280
281#--- TestReplaceText() -----------------------------------------------------
282# function: Test replacing HTML comment with ToC.
283
284sub 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});
296The 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>
303EOT
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>
325EOT
326} # TestReplaceText()
327
328
329 # 7. Test 'numberingStyle'
330TestNumberingStyle();
331 # 8. Test replace comment
332TestReplaceComment();
333 # 9. Test after declaration
334TestAfterDeclaration();
335 # 10. Test replace text
336TestReplaceText();
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
4use strict;
5use Test;
6
7BEGIN { plan tests => 3; }
8
9use HTML::Toc;
10use HTML::TocGenerator;
11use HTML::TocInsertor;
12use HTML::TocUpdator;
13
14
15#--- AssembleTocLine() --------------------------------------------------------
16# function: Assemble ToC line.
17
18sub 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
52sub 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
76sub 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>
197Better 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>
263Thanks 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>
299EOT
300} # TestInsertManualToc()
301
302
303#--- TestInsertManualForUpdating() --------------------------------------------
304# function: Test inserting ToC into manual.
305
306sub 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 -->
427Better 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 -->
493Thanks 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>
529EOT
530} # TestInsertManualForUpdating()
531
532
533#--- TestUpdateManual() -------------------------------------------------------
534# function: Test inserting ToC into manual.
535
536sub 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 -->
657Better 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 -->
723Thanks 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>
759EOT
760} # TestUpdateManual()
761
762
763 # Test inserting ToC into manual
764TestInsertManualToc();
765 # Test inserting ToC with update tokens into manual
766TestInsertManualForUpdating();
767 # Test updating ToC
768TestUpdateManual();
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
4use strict;
5use Test;
6
7BEGIN { plan tests => 5; }
8
9use HTML::Toc;
10use HTML::TocGenerator;
11use HTML::TocInsertor;
12use HTML::TocUpdator;
13
14my ($filename);
15
16BEGIN {
17 # Create test file
18 $filename = "file$$.htm";
19 die "$filename is already there" if -e $filename;
20}
21
22
23END {
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
32sub 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>
40EOT
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 -->
62EOT
63} # TestAttributeToExcludeToken()
64
65
66#--- TestAttributeToTocToken() ------------------------------------------------
67# function: Test 'HTML::Toc' option 'attributeToTocToken'
68
69sub 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>
77EOT
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 -->
100EOT
101} # TestAttributeToTocToken()
102
103
104#--- TestNumberingStyleDecimal ------------------------------------------------
105# function: Test 'decimal' numbering style.
106
107sub 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>
127EOT
128} # TestNumberingStyleDecimal()
129
130
131#--- TestNumberingStyleLowerAlpha ---------------------------------------------
132# function: Test 'lower-alpha' numbering style.
133
134sub 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>
154EOT
155} # TestNumberingStyleLowerAlpha()
156
157
158#--- TestNumberingStyleUpperAlpha ---------------------------------------------
159# function: Test 'upper-alpha' numbering style.
160
161sub 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>
181EOT
182} # TestNumberingStyleUpperAlpha()
183
184
185 # Test 'attributeToTocToken'
186TestAttributeToTocToken();
187 # Test 'attributeToExcludeToken'
188TestAttributeToExcludeToken();
189 # Test 'numberingStyleDecimal'
190TestNumberingStyleDecimal();
191 # Test 'numberingStyleLowerAlpha'
192TestNumberingStyleLowerAlpha();
193 # Test 'numberingStyleUpperAlpha'
194TestNumberingStyleUpperAlpha();
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
5use strict;
6use Test;
7
8BEGIN { plan tests => 13; }
9
10use HTML::Toc;
11use HTML::TocGenerator;
12use HTML::TocInsertor;
13use HTML::TocUpdator;
14
15my ($filename, $filename2);
16
17
18BEGIN {
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
28END {
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
39sub 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>
46EOT
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>
56EOT
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 -->
76EOT
77} # TestExtendFromFile()
78
79
80#--- TestGenerateFromFiles() --------------------------------------------------
81# function: Test 'HTML::TocGenerator->generateFromFile()
82
83sub 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>
90EOT
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>
100EOT
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 -->
119EOT
120} # TestGenerateFromFiles()
121
122
123#--- TestGenerateFromFiles() --------------------------------------------------
124# function: Test 'HTML::TocGenerator->generateFromFile() using multiple files.
125
126sub 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>
135EOT
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 -->
151EOT
152} # TestGenerateFromFile()
153
154
155#--- TestInsertIntoFile() -----------------------------------------------------
156# function: Test 'HTML::TocInsertor->insertIntoFile()
157
158sub 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>
167EOT
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>
189EOT
190} # TestInsertIntoFile()
191
192
193#--- TestInsertIntoFileUsingTocUpdator() --------------------------------------
194# function: Test 'HTML::TocUpdator->insertIntoFile()
195
196sub 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>
207EOT
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>
231EOT
232} # TestInsertIntoFileUsingTocUpdator()
233
234
235#--- TestGlobalGroups0() ------------------------------------------------------
236# function: Test 'HTML::TocGenerator' option 'doUseGroupsGlobal = 0'.
237
238sub 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>
244EOT
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>
271EOT
272} # TestGlobalGroups0()
273
274
275#--- TestGlobalGroups1() ------------------------------------------------------
276# function: Test 'HTML::TocGenerator' option 'doUseGroupsGlobal = 0'.
277
278sub 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>
284EOT
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>
314EOT
315} # TestGlobalGroups1()
316
317
318#--- TestMultipleGroupsAppendix() ---------------------------------------------
319# function: Test multiple ToCs
320
321sub 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>
353EOT
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>
380EOT
381} # TestMultipleGroupsAppendix()
382
383
384#--- TestMultipleGroupsPart() -------------------------------------------------
385# function: Test multiple ToCs
386
387sub 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>
418EOT
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>
450EOT
451} # TestMultipleGroupsPart()
452
453
454#--- TestMultipleTocs() -------------------------------------------------------
455# function: Test multiple ToCs
456
457sub 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>
467EOT
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>
510EOT
511} # TestMultipleTocs()
512
513
514#--- TestSpecifyNumberedList() ------------------------------------------------
515# function: Test specifying numbered list.
516
517sub 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>
525EOT
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 -->
549EOT
550} # TestSpecifyNumberedList()
551
552
553#--- TestUpdateFile() ---------------------------------------------------------
554# function: Test 'HTML::TocUpdator->updateFile()'
555
556sub 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 -->
562foo
563<!-- #EndToc -->
564 <!-- #BeginTocAnchorNameBegin -->bar<!-- #EndTocAnchorNameBegin --><h1>
565 Chapter
566 </h1><!-- #BeginTocAnchorNameEnd -->foo<!-- #EndTocAnchorNameEnd -->
567</body>
568</html>
569EOT
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>
593EOT
594} # TestUpdateFile()
595
596
597#--- TestUsingCSS() -----------------------------------------------------------
598# function: Test multiple ToCs
599
600sub 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>
635EOT
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>
651EOT
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>
680EOT
681} # TestUsingCSS()
682
683
684 # Test 'extendFromFile()'
685TestExtendFromFile();
686 # Test 'generateFromFile()'
687TestGenerateFromFile();
688 # Test 'generateFromFiles()'
689TestGenerateFromFiles();
690 # Test 'doUseGroupsGlobal = 0'
691TestGlobalGroups0();
692 # Test 'doUseGroupsGlobal = 1'
693TestGlobalGroups1();
694 # Test 'tocInsertor->insertIntoFile'
695TestInsertIntoFile();
696 # Test 'tocUpdator->insertIntoFile'
697TestInsertIntoFileUsingTocUpdator();
698 # Test additional 'appendix' group
699TestMultipleGroupsAppendix();
700 # Test additional 'part' group
701TestMultipleGroupsPart();
702 # Test multiple ToCs
703TestMultipleTocs();
704 # Test specifying numbered list
705TestSpecifyNumberedList();
706 # Test 'updateFile()'
707TestUpdateFile();
708 # Test using CSS
709TestUsingCSS();
examples/includes/HTML-Toc-0.91/t/propagate.t+176−0
@@ -0,0 +1,176 @@
1#--- propagate.t --------------------------------------------------------------
2# function: Test ToC propagation.
3
4use strict;
5use Test;
6
7BEGIN { plan tests => 10; }
8
9use HTML::Toc;
10use HTML::TocGenerator;
11use HTML::TocInsertor;
12
13my ($output, $content, $filename);
14my $toc = HTML::Toc->new;
15my $tocGenerator = HTML::TocGenerator->new;
16my $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
27BEGIN {
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>
34EOT
35}
36
37
38END {
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});
47ok($output, "<ul>\n<li>Header\n</ul><h1>Header</h1>");
48
49
50#--- 2. propagateFile ---------------------------------------------------------
51
52$tocInsertor->insertIntoFile($toc, $filename, {'output' => \$output});
53ok($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});
60ok("$output\n", <<'EOT');
61<ul>
62<li><a href=#h-1>Header</a>
63</ul><a name=h-1><h1>Header</h1></a>
64EOT
65
66
67#--- 4. templateAnchorHrefBegin -----------------------------------------------
68
69$toc->setOptions(
70 {'templateAnchorHrefBegin' => '"<$node${file}test${groupId}>"'}
71);
72$tocInsertor->insertIntoFile($toc, $filename, {'output' => \$output});
73ok($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});
84ok($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
90sub 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
102ok($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});
112ok("$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>
116EOT
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
134ok("$output\n", <<'EOT');
135<ul>
136<li><a href=#h-1>Header</a>
137</ul><a name=h-1><h1>-1-Header</h1></a>
138EOT
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
160ok("$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>
164EOT
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
176ok($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
4use strict;
5use Test;
6
7BEGIN { plan tests => 1; }
8
9use Data::Dumper;
10use File::Find;
11use HTML::Toc;
12use HTML::TocGenerator;
13use HTML::TocInsertor;
14use HTML::TocUpdator;
15
16
17 # Create objects
18my $toc = HTML::Toc->new();
19my $tocGenerator = HTML::TocGenerator->new();
20my @fileList;
21
22
23#--- TestSiteMap() ------------------------------------------------------------
24# function: Test specifying numbered list.
25
26sub 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 -->
83EOT
84} # TestSiteMap()
85
86
87#--- WantedSiteMap() ----------------------------------------------------------
88# function: 'Wanted' function, used by File::Find of 'TestSiteMap()'.
89
90sub 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
97TestSiteMap();
examples/includes/HTML-Toc-0.91/t/update.t+114−0
@@ -0,0 +1,114 @@
1#--- update.t -----------------------------------------------------------------
2# function: Test ToC updating.
3
4use strict;
5use Test;
6
7BEGIN { plan tests => 6; }
8
9use HTML::Toc;
10use HTML::TocUpdator;
11
12my ($output, $output2, $content, $filename);
13my $toc = HTML::Toc->new;
14my $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
26BEGIN {
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>
33EOT
34}
35
36
37END {
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});
46ok("$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 -->
50EOT
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 -->
61EOT
62 open(FILE, ">a.out2") || die "Can't create a.out2: $!";
63 print FILE $output2; close(FILE);
64ok($output, $output2);
65
66
67#--- 3. insert ----------------------------------------------------------------
68
69$tocUpdator->insert($toc, "<h1>Header</h1>", {'output' => \$output});
70ok("$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 -->
74EOT
75
76#--- 4. insertIntoFile --------------------------------------------------------
77
78$tocUpdator->insertIntoFile($toc, $filename, {'output' => \$output});
79ok($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 -->
83EOT
84
85
86#--- 5. update twice ----------------------------------------------------------
87
88$tocUpdator->update($toc, "<h1>Header</h1>", {'output' => \$output});
89$tocUpdator->update($toc, $output, {'output' => \$output2});
90ok("$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 -->
94EOT
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});
110ok("$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>
114EOT
examples/includes/PHP-Markdown-Extra-1.2.3/License.text+36−0
@@ -0,0 +1,36 @@
1PHP Markdown & Extra
2Copyright (c) 2004-2008 Michel Fortin
3<http://www.michelf.com/>
4All rights reserved.
5
6Based on Markdown
7Copyright (c) 2003-2006 John Gruber
8<http://daringfireball.net/>
9All rights reserved.
10
11Redistribution and use in source and binary forms, with or without
12modification, are permitted provided that the following conditions are
13met:
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
26This software is provided by the copyright holders and contributors "as
27is" and any express or implied warranties, including, but not limited
28to, the implied warranties of merchantability and fitness for a
29particular purpose are disclaimed. In no event shall the copyright owner
30or contributors be liable for any direct, indirect, incidental, special,
31exemplary, or consequential damages (including, but not limited to,
32procurement of substitute goods or services; loss of use, data, or
33profits; or business interruption) however caused and on any theory of
34liability, whether in contract, strict liability, or tort (including
35negligence or otherwise) arising in any way out of the use of this
36software, 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 @@
1PHP Markdown Extra
2==================
3
4Version 1.2.3 - Wed 31 Dec 2008
5
6by Michel Fortin
7<http://www.michelf.com/>
8
9based on Markdown by John Gruber
10<http://daringfireball.net/>
11
12
13Introduction
14------------
15
16This is a special version of PHP Markdown with extra features. See
17<http://www.michelf.com/projects/php-markdown/extra/> for details.
18
19Markdown is a text-to-HTML conversion tool for web writers. Markdown
20allows you to write using an easy-to-read, easy-to-write plain text
21format, then convert it to structurally valid XHTML (or HTML).
22
23"Markdown" is two things: a plain text markup syntax, and a software
24tool, written in Perl, that converts the plain text markup to HTML.
25PHP Markdown is a port to PHP of the original Markdown program by
26John Gruber.
27
28PHP Markdown can work as a plug-in for WordPress and bBlog, as a
29modifier for the Smarty templating engine, or as a remplacement for
30textile formatting in any software that support textile.
31
32Full documentation of Markdown's syntax is available on John's
33Markdown page: <http://daringfireball.net/projects/markdown/>
34
35
36Installation and Requirement
37----------------------------
38
39PHP Markdown requires PHP version 4.0.5 or later.
40
41
42### WordPress ###
43
44PHP Markdown works with [WordPress][wp], version 1.2 or later.
45
46 [wp]: http://wordpress.org/
47
481. 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
542. 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
603. To post Markdown content, you'll first have to disable the
61 "visual" editor in the User section of WordPress.
62
63You can configure PHP Markdown to not apply to the comments on your
64WordPress weblog. See the "Configuration" section below.
65
66It is not possible at this time to apply a different set of
67filters to different entries. All your entries will be formated by
68PHP Markdown. This is a limitation of WordPress. If your old entries
69are written in HTML (as opposed to another formatting syntax, like
70Textile), they'll probably stay fine after installing Markdown.
71
72
73### bBlog ###
74
75PHP Markdown also works with [bBlog][bb].
76
77 [bb]: http://www.bblog.com/
78
79To use PHP Markdown with bBlog, rename "markdown.php" to
80"modifier.markdown.php" and place the file in the "bBlog_plugins"
81folder. This folder is located inside the "bblog" directory of
82your site, like this:
83
84 (site home)/bblog/bBlog_plugins/modifier.markdown.php
85
86Select "Markdown" as the "Entry Modifier" when you post a new
87entry. 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
93replace Textile by Markdown in TextPattern without having to change
94any code by using the *Texitle Compatibility Mode*. This may work
95with other software that expect Textile too.
96
97 [tx]: http://www.textism.com/tools/textile/
98 [tp]: http://www.textpattern.com/
99
1001. Rename the "markdown.php" file to "classTextile.php". This will
101 make PHP Markdown behave as if it was the actual Textile parser.
102
1032. 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
108Contrary to Textile, Markdown does not convert quotes to curly ones
109and does not convert multiple hyphens (`--` and `---`) into en- and
110em-dashes. If you use PHP Markdown in Textile Compatibility Mode, you
111can solve this problem by installing the "smartypants.php" file from
112[PHP SmartyPants][psp] beside the "classTextile.php" file. The Textile
113Compatibility Mode function will use SmartyPants automatically without
114further modification.
115
116 [psp]: http://www.michelf.com/projects/php-smartypants/
117
118
119### In Your Own Programs ###
120
121You can use PHP Markdown easily in your current PHP program. Simply
122include the file and then call the Markdown function on the text you
123want to convert:
124
125 include_once "markdown.php";
126 $my_html = Markdown($my_text);
127
128If you wish to use PHP Markdown with another text filter function
129built to parse HTML, you should filter the text *after* the Markdown
130function call. This is an example with [PHP SmartyPants][psp]:
131
132 $my_html = SmartyPants(Markdown($my_text));
133
134
135### With Smarty ###
136
137If your program use the [Smarty][sm] template engine, PHP Markdown
138can now be used as a modifier for your templates. Rename "markdown.php"
139to "modifier.markdown.php" and put it in your smarty plugins folder.
140
141 [sm]: http://smarty.php.net/
142
143If you are using MovableType 3.1 or later, the Smarty plugin folder is
144located at `(MT CGI root)/php/extlib/smarty/plugins`. This will allow
145Markdown to work on dynamic pages.
146
147
148### Updating Markdown in Other Programs ###
149
150Many web applications now ship with PHP Markdown, or have plugins to
151perform the conversion to HTML. You can update PHP Markdown -- or
152replace it with PHP Markdown Extra -- in many of these programs by
153swapping the old "markdown.php" file for the new one.
154
155Here is a short non-exhaustive list of some programs and where they
156hide the "markdown.php" file.
157
158| Program | Path to Markdown
159| ------- | ----------------
160| [Pivot][] | `(site home)/pivot/includes/markdown/`
161
162If you're unsure if you can do this with your application, ask the
163developer, or wait for the developer to update his application or
164plugin with the new version of PHP Markdown.
165
166 [Pivot]: http://pivotlog.net/
167
168
169Configuration
170-------------
171
172By default, PHP Markdown produces XHTML output for tags with empty
173elements. E.g.:
174
175 <br />
176
177Markdown can be configured to produce HTML-style tags; e.g.:
178
179 <br>
180
181To do this, you must edit the "MARKDOWN_EMPTY_ELEMENT_SUFFIX"
182definition below the "Global default settings" header at the start of
183the "markdown.php" file.
184
185
186### WordPress-Specific Settings ###
187
188By default, the Markdown plugin applies to both posts and comments on
189your 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
194Bugs
195----
196
197To file bug reports please send email to:
198<michel.fortin@michelf.com>
199
200Please include with your report: (1) the example input; (2) the output you
201expected; (3) the output PHP Markdown actually produced.
202
203
204Version History
205---------------
206
207Extra 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
219Extra 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
2321.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
240Extra 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
246Extra 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
2721.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
316Extra 1.1.7 (26 Sep 2007):
317
3181.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
325Extra 1.1.6 (4 Sep 2007):
326
3271.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
338Extra 1.1.5 (31 Aug 2007):
339
3401.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
351Extra 1.1.4 (3 Aug 2007):
352
3531.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
363Extra 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
3951.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
446Extra 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
4551.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
486Extra 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
5001.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
515Extra 1.1 (1 Dec 2006)
516
517* Added a syntax for footnotes.
518
519* Added an experimental syntax to define abbreviations.
520
521
5221.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
609Extra 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
636Extra 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
649Extra 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
663Extra 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
688Extra 1.0b1 (25 Jun 2005)
689
690* First public release of PHP Markdown Extra.
691
692
693Copyright and License
694---------------------
695
696Copyright (c) 2004-2005 Michel Fortin
697<http://www.michelf.com/>
698All rights reserved.
699
700Based on Markdown
701Copyright (c) 2003-2005 John Gruber
702<http://daringfireball.net/>
703All rights reserved.
704
705Redistribution and use in source and binary forms, with or without
706modification, are permitted provided that the following conditions are
707met:
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
721This software is provided by the copyright holders and contributors "as
722is" and any express or implied warranties, including, but not limited
723to, the implied warranties of merchantability and fitness for a
724particular purpose are disclaimed. In no event shall the copyright owner
725or contributors be liable for any direct, indirect, incidental, special,
726exemplary, or consequential damages (including, but not limited to,
727procurement of substitute goods or services; loss of use, data, or
728profits; or business interruption) however caused and on any theory of
729liability, whether in contract, strict liability, or tort (including
730negligence or otherwise) arising in any way out of the use of this
731software, 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
15define( 'MARKDOWN_VERSION', "1.0.1m" ); # Sat 21 Jun 2008
16define( '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
52function 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/*
71Plugin Name: Markdown Extra
72Plugin URI: http://www.michelf.com/projects/php-markdown/
73Description: <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>
74Version: 1.2.2
75Author: Michel Fortin
76Author URI: http://www.michelf.com/
77*/
78
79if (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
165function 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
181function 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
190if (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
215class 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
1655class 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