prestogres 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (393) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +20 -0
  4. data/LICENSE +202 -0
  5. data/NOTICE +22 -0
  6. data/README.md +217 -0
  7. data/Rakefile +13 -0
  8. data/VERSION +1 -0
  9. data/bin/prestogres +254 -0
  10. data/config/pcp.conf.sample +28 -0
  11. data/config/pgpool.conf +678 -0
  12. data/config/pool_hba.conf +84 -0
  13. data/config/pool_passwd +0 -0
  14. data/config/postgresql.conf +2 -0
  15. data/ext/.gitignore +6 -0
  16. data/ext/depend +26 -0
  17. data/ext/extconf.rb +4 -0
  18. data/ext/prestogres_config.c +12 -0
  19. data/pgpool2/.gitignore +36 -0
  20. data/pgpool2/AUTHORS +4 -0
  21. data/pgpool2/COPYING +12 -0
  22. data/pgpool2/ChangeLog +1 -0
  23. data/pgpool2/INSTALL +1 -0
  24. data/pgpool2/Makefile.am +159 -0
  25. data/pgpool2/Makefile.in +1187 -0
  26. data/pgpool2/NEWS +4960 -0
  27. data/pgpool2/README +1 -0
  28. data/pgpool2/README.euc_jp +1 -0
  29. data/pgpool2/README.online-recovery +62 -0
  30. data/pgpool2/TODO +103 -0
  31. data/pgpool2/ac_func_accept_argtypes.m4 +85 -0
  32. data/pgpool2/aclocal.m4 +1088 -0
  33. data/pgpool2/c-compiler.m4 +134 -0
  34. data/pgpool2/c-library.m4 +325 -0
  35. data/pgpool2/child.c +2097 -0
  36. data/pgpool2/config.guess +1532 -0
  37. data/pgpool2/config.h.in +332 -0
  38. data/pgpool2/config.sub +1640 -0
  39. data/pgpool2/configure +15752 -0
  40. data/pgpool2/configure.in +392 -0
  41. data/pgpool2/depcomp +522 -0
  42. data/pgpool2/doc/basebackup.sh +17 -0
  43. data/pgpool2/doc/pgpool-de.html +4220 -0
  44. data/pgpool2/doc/pgpool-en.html +5738 -0
  45. data/pgpool2/doc/pgpool-fr.html +4118 -0
  46. data/pgpool2/doc/pgpool-ja.css +198 -0
  47. data/pgpool2/doc/pgpool-ja.html +11279 -0
  48. data/pgpool2/doc/pgpool-zh_cn.html +4445 -0
  49. data/pgpool2/doc/pgpool.css +280 -0
  50. data/pgpool2/doc/pgpool_remote_start +13 -0
  51. data/pgpool2/doc/recovery.conf.sample +117 -0
  52. data/pgpool2/doc/tutorial-en.html +707 -0
  53. data/pgpool2/doc/tutorial-ja.html +422 -0
  54. data/pgpool2/doc/tutorial-memqcache-en.html +325 -0
  55. data/pgpool2/doc/tutorial-memqcache-ja.html +370 -0
  56. data/pgpool2/doc/tutorial-memqcache-zh_cn.html +322 -0
  57. data/pgpool2/doc/tutorial-watchdog-en.html +306 -0
  58. data/pgpool2/doc/tutorial-watchdog-ja.html +343 -0
  59. data/pgpool2/doc/tutorial-watchdog-zh_cn.html +301 -0
  60. data/pgpool2/doc/tutorial-zh_cn.html +537 -0
  61. data/pgpool2/doc/watchdog.png +0 -0
  62. data/pgpool2/doc/wd-en.html +236 -0
  63. data/pgpool2/doc/wd-en.jpg +0 -0
  64. data/pgpool2/doc/wd-ja.html +219 -0
  65. data/pgpool2/doc/wd-ja.jpg +0 -0
  66. data/pgpool2/doc/wd-zh_cn.html +201 -0
  67. data/pgpool2/doc/where_to_send_queries.odg +0 -0
  68. data/pgpool2/doc/where_to_send_queries.pdf +0 -0
  69. data/pgpool2/general.m4 +166 -0
  70. data/pgpool2/getopt_long.c +200 -0
  71. data/pgpool2/getopt_long.h +44 -0
  72. data/pgpool2/install-sh +251 -0
  73. data/pgpool2/ltmain.sh +8406 -0
  74. data/pgpool2/m4/libtool.m4 +7360 -0
  75. data/pgpool2/m4/ltoptions.m4 +368 -0
  76. data/pgpool2/m4/ltsugar.m4 +123 -0
  77. data/pgpool2/m4/ltversion.m4 +23 -0
  78. data/pgpool2/m4/lt~obsolete.m4 +92 -0
  79. data/pgpool2/main.c +2971 -0
  80. data/pgpool2/md5.c +444 -0
  81. data/pgpool2/md5.h +28 -0
  82. data/pgpool2/missing +360 -0
  83. data/pgpool2/mkinstalldirs +40 -0
  84. data/pgpool2/parser/Makefile.am +50 -0
  85. data/pgpool2/parser/Makefile.in +559 -0
  86. data/pgpool2/parser/copyfuncs.c +3310 -0
  87. data/pgpool2/parser/gram.c +39100 -0
  88. data/pgpool2/parser/gram.h +940 -0
  89. data/pgpool2/parser/gram.y +13408 -0
  90. data/pgpool2/parser/gramparse.h +74 -0
  91. data/pgpool2/parser/keywords.c +32 -0
  92. data/pgpool2/parser/keywords.h +39 -0
  93. data/pgpool2/parser/kwlist.h +425 -0
  94. data/pgpool2/parser/kwlookup.c +88 -0
  95. data/pgpool2/parser/list.c +1156 -0
  96. data/pgpool2/parser/makefuncs.c +518 -0
  97. data/pgpool2/parser/makefuncs.h +83 -0
  98. data/pgpool2/parser/memnodes.h +79 -0
  99. data/pgpool2/parser/nodes.c +29 -0
  100. data/pgpool2/parser/nodes.h +609 -0
  101. data/pgpool2/parser/outfuncs.c +5790 -0
  102. data/pgpool2/parser/parsenodes.h +2615 -0
  103. data/pgpool2/parser/parser.c +262 -0
  104. data/pgpool2/parser/parser.h +46 -0
  105. data/pgpool2/parser/pg_class.h +158 -0
  106. data/pgpool2/parser/pg_config_manual.h +273 -0
  107. data/pgpool2/parser/pg_list.h +352 -0
  108. data/pgpool2/parser/pg_trigger.h +147 -0
  109. data/pgpool2/parser/pg_wchar.h +492 -0
  110. data/pgpool2/parser/pool_memory.c +342 -0
  111. data/pgpool2/parser/pool_memory.h +77 -0
  112. data/pgpool2/parser/pool_parser.h +222 -0
  113. data/pgpool2/parser/pool_string.c +121 -0
  114. data/pgpool2/parser/pool_string.h +37 -0
  115. data/pgpool2/parser/primnodes.h +1280 -0
  116. data/pgpool2/parser/scan.c +4094 -0
  117. data/pgpool2/parser/scan.l +1451 -0
  118. data/pgpool2/parser/scanner.h +120 -0
  119. data/pgpool2/parser/scansup.c +221 -0
  120. data/pgpool2/parser/scansup.h +28 -0
  121. data/pgpool2/parser/snprintf.c +1102 -0
  122. data/pgpool2/parser/stringinfo.c +294 -0
  123. data/pgpool2/parser/stringinfo.h +178 -0
  124. data/pgpool2/parser/value.c +78 -0
  125. data/pgpool2/parser/value.h +62 -0
  126. data/pgpool2/parser/wchar.c +2048 -0
  127. data/pgpool2/pcp.conf.sample +28 -0
  128. data/pgpool2/pcp/Makefile.am +40 -0
  129. data/pgpool2/pcp/Makefile.in +771 -0
  130. data/pgpool2/pcp/libpcp_ext.h +250 -0
  131. data/pgpool2/pcp/md5.c +444 -0
  132. data/pgpool2/pcp/md5.h +28 -0
  133. data/pgpool2/pcp/pcp.c +1652 -0
  134. data/pgpool2/pcp/pcp.h +61 -0
  135. data/pgpool2/pcp/pcp_attach_node.c +172 -0
  136. data/pgpool2/pcp/pcp_detach_node.c +185 -0
  137. data/pgpool2/pcp/pcp_error.c +87 -0
  138. data/pgpool2/pcp/pcp_node_count.c +160 -0
  139. data/pgpool2/pcp/pcp_node_info.c +198 -0
  140. data/pgpool2/pcp/pcp_pool_status.c +166 -0
  141. data/pgpool2/pcp/pcp_proc_count.c +166 -0
  142. data/pgpool2/pcp/pcp_proc_info.c +261 -0
  143. data/pgpool2/pcp/pcp_promote_node.c +185 -0
  144. data/pgpool2/pcp/pcp_recovery_node.c +172 -0
  145. data/pgpool2/pcp/pcp_stop_pgpool.c +179 -0
  146. data/pgpool2/pcp/pcp_stream.c +385 -0
  147. data/pgpool2/pcp/pcp_stream.h +52 -0
  148. data/pgpool2/pcp/pcp_systemdb_info.c +194 -0
  149. data/pgpool2/pcp/pcp_watchdog_info.c +211 -0
  150. data/pgpool2/pcp_child.c +1493 -0
  151. data/pgpool2/pg_md5.c +305 -0
  152. data/pgpool2/pgpool.8.in +121 -0
  153. data/pgpool2/pgpool.conf +553 -0
  154. data/pgpool2/pgpool.conf.sample +666 -0
  155. data/pgpool2/pgpool.conf.sample-master-slave +665 -0
  156. data/pgpool2/pgpool.conf.sample-replication +664 -0
  157. data/pgpool2/pgpool.conf.sample-stream +664 -0
  158. data/pgpool2/pgpool.spec +264 -0
  159. data/pgpool2/pgpool_adm/TODO +7 -0
  160. data/pgpool2/pgpool_adm/pgpool_adm--1.0.sql +85 -0
  161. data/pgpool2/pgpool_adm/pgpool_adm.c +558 -0
  162. data/pgpool2/pgpool_adm/pgpool_adm.control +5 -0
  163. data/pgpool2/pgpool_adm/pgpool_adm.h +46 -0
  164. data/pgpool2/pgpool_adm/pgpool_adm.sql.in +85 -0
  165. data/pgpool2/pool.h +655 -0
  166. data/pgpool2/pool_auth.c +1390 -0
  167. data/pgpool2/pool_config.c +5007 -0
  168. data/pgpool2/pool_config.h +284 -0
  169. data/pgpool2/pool_config.l +3281 -0
  170. data/pgpool2/pool_config_md5.c +29 -0
  171. data/pgpool2/pool_connection_pool.c +812 -0
  172. data/pgpool2/pool_error.c +242 -0
  173. data/pgpool2/pool_globals.c +27 -0
  174. data/pgpool2/pool_hba.c +1723 -0
  175. data/pgpool2/pool_hba.conf.sample +67 -0
  176. data/pgpool2/pool_ip.c +567 -0
  177. data/pgpool2/pool_ip.h +65 -0
  178. data/pgpool2/pool_ipc.h +38 -0
  179. data/pgpool2/pool_lobj.c +242 -0
  180. data/pgpool2/pool_lobj.h +32 -0
  181. data/pgpool2/pool_memqcache.c +3818 -0
  182. data/pgpool2/pool_memqcache.h +268 -0
  183. data/pgpool2/pool_params.c +163 -0
  184. data/pgpool2/pool_passwd.c +249 -0
  185. data/pgpool2/pool_passwd.h +41 -0
  186. data/pgpool2/pool_path.c +193 -0
  187. data/pgpool2/pool_path.h +81 -0
  188. data/pgpool2/pool_process_context.c +247 -0
  189. data/pgpool2/pool_process_context.h +62 -0
  190. data/pgpool2/pool_process_query.c +5001 -0
  191. data/pgpool2/pool_process_reporting.c +1671 -0
  192. data/pgpool2/pool_process_reporting.h +44 -0
  193. data/pgpool2/pool_proto2.c +671 -0
  194. data/pgpool2/pool_proto_modules.c +3524 -0
  195. data/pgpool2/pool_proto_modules.h +185 -0
  196. data/pgpool2/pool_query_cache.c +1020 -0
  197. data/pgpool2/pool_query_context.c +1871 -0
  198. data/pgpool2/pool_query_context.h +105 -0
  199. data/pgpool2/pool_relcache.c +284 -0
  200. data/pgpool2/pool_relcache.h +78 -0
  201. data/pgpool2/pool_rewrite_outfuncs.c +9060 -0
  202. data/pgpool2/pool_rewrite_query.c +715 -0
  203. data/pgpool2/pool_rewrite_query.h +192 -0
  204. data/pgpool2/pool_select_walker.c +1150 -0
  205. data/pgpool2/pool_select_walker.h +68 -0
  206. data/pgpool2/pool_sema.c +161 -0
  207. data/pgpool2/pool_session_context.c +952 -0
  208. data/pgpool2/pool_session_context.h +203 -0
  209. data/pgpool2/pool_shmem.c +185 -0
  210. data/pgpool2/pool_signal.c +158 -0
  211. data/pgpool2/pool_signal.h +61 -0
  212. data/pgpool2/pool_ssl.c +339 -0
  213. data/pgpool2/pool_stream.c +962 -0
  214. data/pgpool2/pool_stream.h +61 -0
  215. data/pgpool2/pool_system.c +659 -0
  216. data/pgpool2/pool_timestamp.c +1215 -0
  217. data/pgpool2/pool_timestamp.h +38 -0
  218. data/pgpool2/pool_type.h +171 -0
  219. data/pgpool2/pool_worker_child.c +384 -0
  220. data/pgpool2/ps_status.c +404 -0
  221. data/pgpool2/recovery.c +435 -0
  222. data/pgpool2/redhat/pgpool.conf.sample.patch +52 -0
  223. data/pgpool2/redhat/pgpool.init +201 -0
  224. data/pgpool2/redhat/pgpool.sysconfig +7 -0
  225. data/pgpool2/redhat/rpm_installer/basebackup-replication.sh +53 -0
  226. data/pgpool2/redhat/rpm_installer/basebackup-stream.sh +55 -0
  227. data/pgpool2/redhat/rpm_installer/config_for_script +17 -0
  228. data/pgpool2/redhat/rpm_installer/failover.sh +64 -0
  229. data/pgpool2/redhat/rpm_installer/getsources.sh +141 -0
  230. data/pgpool2/redhat/rpm_installer/install.sh +1363 -0
  231. data/pgpool2/redhat/rpm_installer/pgpool_recovery_pitr +47 -0
  232. data/pgpool2/redhat/rpm_installer/pgpool_remote_start +15 -0
  233. data/pgpool2/redhat/rpm_installer/recovery.conf +4 -0
  234. data/pgpool2/redhat/rpm_installer/uninstall.sh +57 -0
  235. data/pgpool2/sample/dist_def_pgbench.sql +73 -0
  236. data/pgpool2/sample/pgpool.pam +3 -0
  237. data/pgpool2/sample/pgpool_recovery +20 -0
  238. data/pgpool2/sample/pgpool_recovery_pitr +19 -0
  239. data/pgpool2/sample/pgpool_remote_start +13 -0
  240. data/pgpool2/sample/replicate_def_pgbench.sql +18 -0
  241. data/pgpool2/sql/insert_lock.sql +15 -0
  242. data/pgpool2/sql/pgpool-recovery/pgpool-recovery.c +280 -0
  243. data/pgpool2/sql/pgpool-recovery/pgpool-recovery.sql.in +19 -0
  244. data/pgpool2/sql/pgpool-recovery/pgpool_recovery--1.0.sql +24 -0
  245. data/pgpool2/sql/pgpool-recovery/pgpool_recovery.control +5 -0
  246. data/pgpool2/sql/pgpool-recovery/uninstall_pgpool-recovery.sql +3 -0
  247. data/pgpool2/sql/pgpool-regclass/pgpool-regclass.c +206 -0
  248. data/pgpool2/sql/pgpool-regclass/pgpool-regclass.sql.in +4 -0
  249. data/pgpool2/sql/pgpool-regclass/pgpool_regclass--1.0.sql +7 -0
  250. data/pgpool2/sql/pgpool-regclass/pgpool_regclass.control +5 -0
  251. data/pgpool2/sql/pgpool-regclass/uninstall_pgpool-regclass.sql +1 -0
  252. data/pgpool2/sql/system_db.sql +38 -0
  253. data/pgpool2/strlcpy.c +85 -0
  254. data/pgpool2/test/C/test_extended.c +98 -0
  255. data/pgpool2/test/jdbc/.cvsignore +2 -0
  256. data/pgpool2/test/jdbc/AutoCommitTest.java +45 -0
  257. data/pgpool2/test/jdbc/BatchTest.java +55 -0
  258. data/pgpool2/test/jdbc/ColumnTest.java +60 -0
  259. data/pgpool2/test/jdbc/CreateTempTableTest.java +48 -0
  260. data/pgpool2/test/jdbc/InsertTest.java +34 -0
  261. data/pgpool2/test/jdbc/LockTest.java +36 -0
  262. data/pgpool2/test/jdbc/PgpoolTest.java +75 -0
  263. data/pgpool2/test/jdbc/README.euc_jp +73 -0
  264. data/pgpool2/test/jdbc/RunTest.java +83 -0
  265. data/pgpool2/test/jdbc/SelectTest.java +37 -0
  266. data/pgpool2/test/jdbc/UpdateTest.java +32 -0
  267. data/pgpool2/test/jdbc/expected/CreateTempTable +1 -0
  268. data/pgpool2/test/jdbc/expected/autocommit +10 -0
  269. data/pgpool2/test/jdbc/expected/batch +1 -0
  270. data/pgpool2/test/jdbc/expected/column +100 -0
  271. data/pgpool2/test/jdbc/expected/insert +1 -0
  272. data/pgpool2/test/jdbc/expected/lock +100 -0
  273. data/pgpool2/test/jdbc/expected/select +2 -0
  274. data/pgpool2/test/jdbc/expected/update +1 -0
  275. data/pgpool2/test/jdbc/pgpool.properties +7 -0
  276. data/pgpool2/test/jdbc/prepare.sql +54 -0
  277. data/pgpool2/test/jdbc/run.sh +6 -0
  278. data/pgpool2/test/parser/.cvsignore +6 -0
  279. data/pgpool2/test/parser/README +32 -0
  280. data/pgpool2/test/parser/expected/copy.out +17 -0
  281. data/pgpool2/test/parser/expected/create.out +64 -0
  282. data/pgpool2/test/parser/expected/cursor.out +37 -0
  283. data/pgpool2/test/parser/expected/delete.out +10 -0
  284. data/pgpool2/test/parser/expected/drop.out +12 -0
  285. data/pgpool2/test/parser/expected/insert.out +13 -0
  286. data/pgpool2/test/parser/expected/misc.out +28 -0
  287. data/pgpool2/test/parser/expected/prepare.out +4 -0
  288. data/pgpool2/test/parser/expected/privileges.out +31 -0
  289. data/pgpool2/test/parser/expected/scanner.out +30 -0
  290. data/pgpool2/test/parser/expected/select.out +89 -0
  291. data/pgpool2/test/parser/expected/transaction.out +38 -0
  292. data/pgpool2/test/parser/expected/update.out +11 -0
  293. data/pgpool2/test/parser/expected/v84.out +37 -0
  294. data/pgpool2/test/parser/expected/v90.out +25 -0
  295. data/pgpool2/test/parser/expected/var.out +22 -0
  296. data/pgpool2/test/parser/input/alter.sql +2 -0
  297. data/pgpool2/test/parser/input/copy.sql +17 -0
  298. data/pgpool2/test/parser/input/create.sql +64 -0
  299. data/pgpool2/test/parser/input/cursor.sql +37 -0
  300. data/pgpool2/test/parser/input/delete.sql +10 -0
  301. data/pgpool2/test/parser/input/drop.sql +12 -0
  302. data/pgpool2/test/parser/input/insert.sql +13 -0
  303. data/pgpool2/test/parser/input/misc.sql +28 -0
  304. data/pgpool2/test/parser/input/prepare.sql +4 -0
  305. data/pgpool2/test/parser/input/privileges.sql +31 -0
  306. data/pgpool2/test/parser/input/scanner.sql +34 -0
  307. data/pgpool2/test/parser/input/select.sql +89 -0
  308. data/pgpool2/test/parser/input/transaction.sql +38 -0
  309. data/pgpool2/test/parser/input/update.sql +11 -0
  310. data/pgpool2/test/parser/input/v84.sql +37 -0
  311. data/pgpool2/test/parser/input/v90.sql +38 -0
  312. data/pgpool2/test/parser/input/var.sql +22 -0
  313. data/pgpool2/test/parser/main.c +96 -0
  314. data/pgpool2/test/parser/parse_schedule +16 -0
  315. data/pgpool2/test/parser/pool.h +13 -0
  316. data/pgpool2/test/parser/run-test +62 -0
  317. data/pgpool2/test/pdo-test/README.euc_jp +58 -0
  318. data/pgpool2/test/pdo-test/SQLlist/test1.sql +3 -0
  319. data/pgpool2/test/pdo-test/SQLlist/test2.sql +3 -0
  320. data/pgpool2/test/pdo-test/collections.inc +11 -0
  321. data/pgpool2/test/pdo-test/def.inc +7 -0
  322. data/pgpool2/test/pdo-test/log.txt +0 -0
  323. data/pgpool2/test/pdo-test/mod/database.inc +36 -0
  324. data/pgpool2/test/pdo-test/mod/def.inc +0 -0
  325. data/pgpool2/test/pdo-test/mod/errorhandler.inc +27 -0
  326. data/pgpool2/test/pdo-test/pdotest.php +11 -0
  327. data/pgpool2/test/pdo-test/regsql.inc +56 -0
  328. data/pgpool2/test/pgpool_setup +898 -0
  329. data/pgpool2/test/regression/README +39 -0
  330. data/pgpool2/test/regression/clean.sh +21 -0
  331. data/pgpool2/test/regression/libs.sh +16 -0
  332. data/pgpool2/test/regression/regress.sh +166 -0
  333. data/pgpool2/test/regression/tests/001.load_balance/test.sh +128 -0
  334. data/pgpool2/test/regression/tests/002.native_replication/PgTester.java +47 -0
  335. data/pgpool2/test/regression/tests/002.native_replication/create.sql +6 -0
  336. data/pgpool2/test/regression/tests/002.native_replication/test.sh +71 -0
  337. data/pgpool2/test/regression/tests/003.failover/expected.r +6 -0
  338. data/pgpool2/test/regression/tests/003.failover/expected.s +6 -0
  339. data/pgpool2/test/regression/tests/003.failover/test.sh +45 -0
  340. data/pgpool2/test/regression/tests/004.watchdog/master.conf +12 -0
  341. data/pgpool2/test/regression/tests/004.watchdog/standby.conf +19 -0
  342. data/pgpool2/test/regression/tests/004.watchdog/test.sh +52 -0
  343. data/pgpool2/test/regression/tests/050.bug58/test.sh +50 -0
  344. data/pgpool2/test/regression/tests/051.bug60/bug.sql +12 -0
  345. data/pgpool2/test/regression/tests/051.bug60/database-clean.sql +6 -0
  346. data/pgpool2/test/regression/tests/051.bug60/database-setup.sql +28 -0
  347. data/pgpool2/test/regression/tests/051.bug60/test.sh +79 -0
  348. data/pgpool2/test/regression/tests/052.do_query/test.sh +44 -0
  349. data/pgpool2/test/regression/tests/053.insert_lock_hangs/test.sh +81 -0
  350. data/pgpool2/test/regression/tests/054.postgres_fdw/test.sh +67 -0
  351. data/pgpool2/test/regression/tests/055.backend_all_down/test.sh +52 -0
  352. data/pgpool2/test/regression/tests/056.bug63/jdbctest2.java +66 -0
  353. data/pgpool2/test/regression/tests/056.bug63/test.sh +47 -0
  354. data/pgpool2/test/regression/tests/057.bug61/test.sh +40 -0
  355. data/pgpool2/test/regression/tests/058.bug68/jdbctest3.java +45 -0
  356. data/pgpool2/test/regression/tests/058.bug68/test.sh +47 -0
  357. data/pgpool2/test/timestamp/expected/insert.out +16 -0
  358. data/pgpool2/test/timestamp/expected/misc.out +3 -0
  359. data/pgpool2/test/timestamp/expected/update.out +6 -0
  360. data/pgpool2/test/timestamp/input/insert.sql +16 -0
  361. data/pgpool2/test/timestamp/input/misc.sql +3 -0
  362. data/pgpool2/test/timestamp/input/update.sql +6 -0
  363. data/pgpool2/test/timestamp/main.c +129 -0
  364. data/pgpool2/test/timestamp/parse_schedule +3 -0
  365. data/pgpool2/test/timestamp/run-test +69 -0
  366. data/pgpool2/version.h +1 -0
  367. data/pgpool2/watchdog/Makefile.am +17 -0
  368. data/pgpool2/watchdog/Makefile.in +505 -0
  369. data/pgpool2/watchdog/test/stab.c +266 -0
  370. data/pgpool2/watchdog/test/test.c +85 -0
  371. data/pgpool2/watchdog/test/wd_child_t.c +87 -0
  372. data/pgpool2/watchdog/test/wd_lifecheck_t.c +87 -0
  373. data/pgpool2/watchdog/test/wd_packet_t.c +87 -0
  374. data/pgpool2/watchdog/test/wd_ping_t.c +20 -0
  375. data/pgpool2/watchdog/watchdog.c +408 -0
  376. data/pgpool2/watchdog/watchdog.h +209 -0
  377. data/pgpool2/watchdog/wd_child.c +444 -0
  378. data/pgpool2/watchdog/wd_ext.h +123 -0
  379. data/pgpool2/watchdog/wd_heartbeat.c +577 -0
  380. data/pgpool2/watchdog/wd_if.c +216 -0
  381. data/pgpool2/watchdog/wd_init.c +126 -0
  382. data/pgpool2/watchdog/wd_interlock.c +347 -0
  383. data/pgpool2/watchdog/wd_lifecheck.c +512 -0
  384. data/pgpool2/watchdog/wd_list.c +429 -0
  385. data/pgpool2/watchdog/wd_packet.c +1159 -0
  386. data/pgpool2/watchdog/wd_ping.c +330 -0
  387. data/pgpool2/ylwrap +223 -0
  388. data/pgsql/presto_client.py +346 -0
  389. data/pgsql/prestogres.py +156 -0
  390. data/pgsql/setup_functions.sql +21 -0
  391. data/pgsql/setup_language.sql +3 -0
  392. data/prestogres.gemspec +23 -0
  393. metadata +496 -0
@@ -0,0 +1,120 @@
1
+ /*-------------------------------------------------------------------------
2
+ *
3
+ * scanner.h
4
+ * API for the core scanner (flex machine)
5
+ *
6
+ * The core scanner is also used by PL/pgsql, so we provide a public API
7
+ * for it. However, the rest of the backend is only expected to use the
8
+ * higher-level API provided by parser.h.
9
+ *
10
+ *
11
+ * Portions Copyright (c) 2003-2013, PgPool Global Development Group
12
+ * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
13
+ * Portions Copyright (c) 1994, Regents of the University of California
14
+ *
15
+ * src/include/parser/scanner.h
16
+ *
17
+ *-------------------------------------------------------------------------
18
+ */
19
+
20
+ #ifndef SCANNER_H
21
+ #define SCANNER_H
22
+
23
+ #include "keywords.h"
24
+
25
+ /*
26
+ * The scanner returns extra data about scanned tokens in this union type.
27
+ * Note that this is a subset of the fields used in YYSTYPE of the bison
28
+ * parsers built atop the scanner.
29
+ */
30
+ typedef union core_YYSTYPE
31
+ {
32
+ int ival; /* for integer literals */
33
+ char *str; /* for identifiers and non-integer literals */
34
+ const char *keyword; /* canonical spelling of keywords */
35
+ } core_YYSTYPE;
36
+
37
+ /*
38
+ * We track token locations in terms of byte offsets from the start of the
39
+ * source string, not the column number/line number representation that
40
+ * bison uses by default. Also, to minimize overhead we track only one
41
+ * location (usually the first token location) for each construct, not
42
+ * the beginning and ending locations as bison does by default. It's
43
+ * therefore sufficient to make YYLTYPE an int.
44
+ */
45
+ #define YYLTYPE int
46
+
47
+ /*
48
+ * Another important component of the scanner's API is the token code numbers.
49
+ * However, those are not defined in this file, because bison insists on
50
+ * defining them for itself. The token codes used by the core scanner are
51
+ * the ASCII characters plus these:
52
+ * %token <str> IDENT FCONST SCONST BCONST XCONST Op
53
+ * %token <ival> ICONST PARAM
54
+ * %token TYPECAST DOT_DOT COLON_EQUALS
55
+ * The above token definitions *must* be the first ones declared in any
56
+ * bison parser built atop this scanner, so that they will have consistent
57
+ * numbers assigned to them (specifically, IDENT = 258 and so on).
58
+ */
59
+
60
+ /*
61
+ * The YY_EXTRA data that a flex scanner allows us to pass around.
62
+ * Private state needed by the core scanner goes here. Note that the actual
63
+ * yy_extra struct may be larger and have this as its first component, thus
64
+ * allowing the calling parser to keep some fields of its own in YY_EXTRA.
65
+ */
66
+ typedef struct core_yy_extra_type
67
+ {
68
+ /*
69
+ * The string the scanner is physically scanning. We keep this mainly so
70
+ * that we can cheaply compute the offset of the current token (yytext).
71
+ */
72
+ char *scanbuf;
73
+ Size scanbuflen;
74
+
75
+ /*
76
+ * The keyword list to use.
77
+ */
78
+ const ScanKeyword *keywords;
79
+ int num_keywords;
80
+
81
+ /*
82
+ * literalbuf is used to accumulate literal values when multiple rules are
83
+ * needed to parse a single literal. Call startlit() to reset buffer to
84
+ * empty, addlit() to add text. NOTE: the string in literalbuf is NOT
85
+ * necessarily null-terminated, but there always IS room to add a trailing
86
+ * null at offset literallen. We store a null only when we need it.
87
+ */
88
+ char *literalbuf; /* palloc'd expandable buffer */
89
+ int literallen; /* actual current string length */
90
+ int literalalloc; /* current allocated buffer size */
91
+
92
+ int xcdepth; /* depth of nesting in slash-star comments */
93
+ char *dolqstart; /* current $foo$ quote start string */
94
+
95
+ /* first part of UTF16 surrogate pair for Unicode escapes */
96
+ int32 utf16_first_part;
97
+
98
+ /* state variables for literal-lexing warnings */
99
+ bool warn_on_first_escape;
100
+ bool saw_non_ascii;
101
+ } core_yy_extra_type;
102
+
103
+ /*
104
+ * The type of yyscanner is opaque outside scan.l.
105
+ */
106
+ typedef void *core_yyscan_t;
107
+
108
+
109
+ /* Entry points in parser/scan.l */
110
+ extern core_yyscan_t scanner_init(const char *str,
111
+ core_yy_extra_type *yyext,
112
+ const ScanKeyword *keywords,
113
+ int num_keywords);
114
+ extern void scanner_finish(core_yyscan_t yyscanner);
115
+ extern int core_yylex(core_YYSTYPE *lvalp, YYLTYPE *llocp,
116
+ core_yyscan_t yyscanner);
117
+ extern int scanner_errposition(int location, core_yyscan_t yyscanner);
118
+ extern void scanner_yyerror(const char *message, core_yyscan_t yyscanner);
119
+
120
+ #endif /* SCANNER_H */
@@ -0,0 +1,221 @@
1
+ /*-------------------------------------------------------------------------
2
+ *
3
+ * scansup.c
4
+ * support routines for the lex/flex scanner, used by both the normal
5
+ * backend as well as the bootstrap backend
6
+ *
7
+ * Portions Copyright (c) 1996-2013, PgPool Global Development Group
8
+ * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
9
+ * Portions Copyright (c) 1994, Regents of the University of California
10
+ *
11
+ *
12
+ * IDENTIFICATION
13
+ * src/backend/parser/scansup.c
14
+ *
15
+ *-------------------------------------------------------------------------
16
+ */
17
+ #include "pool_parser.h"
18
+ #include "pool_memory.h"
19
+
20
+ #include <ctype.h>
21
+ #include <string.h>
22
+
23
+ #include "scansup.h"
24
+ #include "pg_wchar.h"
25
+
26
+
27
+ /* ----------------
28
+ * scanstr
29
+ *
30
+ * if the string passed in has escaped codes, map the escape codes to actual
31
+ * chars
32
+ *
33
+ * the string returned is palloc'd and should eventually be pfree'd by the
34
+ * caller!
35
+ * ----------------
36
+ */
37
+ char *
38
+ scanstr(const char *s)
39
+ {
40
+ char *newStr;
41
+ int len,
42
+ i,
43
+ j;
44
+
45
+ if (s == NULL || s[0] == '\0')
46
+ return pstrdup("");
47
+
48
+ len = strlen(s);
49
+
50
+ newStr = palloc(len + 1); /* string cannot get longer */
51
+
52
+ for (i = 0, j = 0; i < len; i++)
53
+ {
54
+ if (s[i] == '\'')
55
+ {
56
+ /*
57
+ * Note: if scanner is working right, unescaped quotes can only
58
+ * appear in pairs, so there should be another character.
59
+ */
60
+ i++;
61
+ newStr[j] = s[i];
62
+ }
63
+ else if (s[i] == '\\')
64
+ {
65
+ i++;
66
+ switch (s[i])
67
+ {
68
+ case 'b':
69
+ newStr[j] = '\b';
70
+ break;
71
+ case 'f':
72
+ newStr[j] = '\f';
73
+ break;
74
+ case 'n':
75
+ newStr[j] = '\n';
76
+ break;
77
+ case 'r':
78
+ newStr[j] = '\r';
79
+ break;
80
+ case 't':
81
+ newStr[j] = '\t';
82
+ break;
83
+ case '0':
84
+ case '1':
85
+ case '2':
86
+ case '3':
87
+ case '4':
88
+ case '5':
89
+ case '6':
90
+ case '7':
91
+ {
92
+ int k;
93
+ long octVal = 0;
94
+
95
+ for (k = 0;
96
+ s[i + k] >= '0' && s[i + k] <= '7' && k < 3;
97
+ k++)
98
+ octVal = (octVal << 3) + (s[i + k] - '0');
99
+ i += k - 1;
100
+ newStr[j] = ((char) octVal);
101
+ }
102
+ break;
103
+ default:
104
+ newStr[j] = s[i];
105
+ break;
106
+ } /* switch */
107
+ } /* s[i] == '\\' */
108
+ else
109
+ newStr[j] = s[i];
110
+ j++;
111
+ }
112
+ newStr[j] = '\0';
113
+ return newStr;
114
+ }
115
+
116
+
117
+ /*
118
+ * downcase_truncate_identifier() --- do appropriate downcasing and
119
+ * truncation of an unquoted identifier. Optionally warn of truncation.
120
+ *
121
+ * Returns a palloc'd string containing the adjusted identifier.
122
+ *
123
+ * Note: in some usages the passed string is not null-terminated.
124
+ *
125
+ * Note: the API of this function is designed to allow for downcasing
126
+ * transformations that increase the string length, but we don't yet
127
+ * support that. If you want to implement it, you'll need to fix
128
+ * SplitIdentifierString() in utils/adt/varlena.c.
129
+ */
130
+ char *
131
+ downcase_truncate_identifier(const char *ident, int len, bool warn)
132
+ {
133
+ char *result;
134
+ int i;
135
+
136
+ result = palloc(len + 1);
137
+
138
+ /*
139
+ * SQL99 specifies Unicode-aware case normalization, which we don't yet
140
+ * have the infrastructure for. Instead we use tolower() to provide a
141
+ * locale-aware translation. However, there are some locales where this
142
+ * is not right either (eg, Turkish may do strange things with 'i' and
143
+ * 'I'). Our current compromise is to use tolower() for characters with
144
+ * the high bit set, and use an ASCII-only downcasing for 7-bit
145
+ * characters.
146
+ */
147
+ for (i = 0; i < len; i++)
148
+ {
149
+ unsigned char ch = (unsigned char) ident[i];
150
+
151
+ if (ch >= 'A' && ch <= 'Z')
152
+ ch += 'a' - 'A';
153
+ else if (IS_HIGHBIT_SET(ch) && isupper(ch))
154
+ ch = tolower(ch);
155
+ result[i] = (char) ch;
156
+ }
157
+ result[i] = '\0';
158
+
159
+ if (i >= NAMEDATALEN)
160
+ truncate_identifier(result, i, warn);
161
+
162
+ return result;
163
+ }
164
+
165
+ /*
166
+ * truncate_identifier() --- truncate an identifier to NAMEDATALEN-1 bytes.
167
+ *
168
+ * The given string is modified in-place, if necessary. A warning is
169
+ * issued if requested.
170
+ *
171
+ * We require the caller to pass in the string length since this saves a
172
+ * strlen() call in some common usages.
173
+ */
174
+ void
175
+ truncate_identifier(char *ident, int len, bool warn)
176
+ {
177
+ #if PGPOOL_NOT_USED
178
+ if (len >= NAMEDATALEN)
179
+ {
180
+ len = pg_mbcliplen(ident, len, NAMEDATALEN - 1);
181
+ if (warn)
182
+ {
183
+ /*
184
+ * We avoid using %.*s here because it can misbehave if the data
185
+ * is not valid in what libc thinks is the prevailing encoding.
186
+ */
187
+ char buf[NAMEDATALEN];
188
+
189
+ memcpy(buf, ident, len);
190
+ buf[len] = '\0';
191
+ ereport(NOTICE,
192
+ (errcode(ERRCODE_NAME_TOO_LONG),
193
+ errmsg("identifier \"%s\" will be truncated to \"%s\"",
194
+ ident, buf)));
195
+ }
196
+ ident[len] = '\0';
197
+ }
198
+ #endif
199
+ }
200
+
201
+ /*
202
+ * scanner_isspace() --- return TRUE if flex scanner considers char whitespace
203
+ *
204
+ * This should be used instead of the potentially locale-dependent isspace()
205
+ * function when it's important to match the lexer's behavior.
206
+ *
207
+ * In principle we might need similar functions for isalnum etc, but for the
208
+ * moment only isspace seems needed.
209
+ */
210
+ bool
211
+ scanner_isspace(char ch)
212
+ {
213
+ /* This must match scan.l's list of {space} characters */
214
+ if (ch == ' ' ||
215
+ ch == '\t' ||
216
+ ch == '\n' ||
217
+ ch == '\r' ||
218
+ ch == '\f')
219
+ return true;
220
+ return false;
221
+ }
@@ -0,0 +1,28 @@
1
+ /*-------------------------------------------------------------------------
2
+ *
3
+ * scansup.h
4
+ * scanner support routines. used by both the bootstrap lexer
5
+ * as well as the normal lexer
6
+ *
7
+ * Portions Copyright (c) 2003-2013, PgPool Global Development Group
8
+ * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
9
+ * Portions Copyright (c) 1994, Regents of the University of California
10
+ *
11
+ * src/include/parser/scansup.h
12
+ *
13
+ *-------------------------------------------------------------------------
14
+ */
15
+
16
+ #ifndef SCANSUP_H
17
+ #define SCANSUP_H
18
+
19
+ extern char *scanstr(const char *s);
20
+
21
+ extern char *downcase_truncate_identifier(const char *ident, int len,
22
+ bool warn);
23
+
24
+ extern void truncate_identifier(char *ident, int len, bool warn);
25
+
26
+ extern bool scanner_isspace(char ch);
27
+
28
+ #endif /* SCANSUP_H */
@@ -0,0 +1,1102 @@
1
+ /*
2
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
3
+ * Copyright (c) 1988, 1993
4
+ * The Regents of the University of California. All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions
8
+ * are met:
9
+ * 1. Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * 2. Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * 3. Neither the name of the University nor the names of its contributors
15
+ * may be used to endorse or promote products derived from this software
16
+ * without specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
+ * SUCH DAMAGE.
29
+ *
30
+ * src/port/snprintf.c
31
+ */
32
+
33
+ /*
34
+ #include "c.h"
35
+
36
+ #include <limits.h>
37
+ #ifndef WIN32
38
+ #include <sys/ioctl.h>
39
+ #endif
40
+ #include <sys/param.h>
41
+ */
42
+
43
+ #ifndef NL_ARGMAX
44
+ #define NL_ARGMAX 16
45
+ #endif
46
+
47
+ #include <stdarg.h>
48
+ #include <stdio.h>
49
+ #include <stdint.h>
50
+ #include <stdlib.h>
51
+ #include <string.h>
52
+ #include <ctype.h>
53
+ #include <errno.h>
54
+ #include "pool_memory.h"
55
+ #include "pool_parser.h"
56
+ #include "stringinfo.h"
57
+
58
+ /* --------------------------------------------------------------------- */
59
+ /* c.h */
60
+ /* --------------------------------------------------------------------- */
61
+
62
+ /* Get a bit mask of the bits set in non-long aligned addresses */
63
+ #define LONG_ALIGN_MASK (sizeof(long) - 1)
64
+
65
+ #define MEMSET_LOOP_LIMIT 1024
66
+
67
+ /*
68
+ * MemSet
69
+ * Exactly the same as standard library function memset(), but considerably
70
+ * faster for zeroing small word-aligned structures (such as parsetree nodes).
71
+ * This has to be a macro because the main point is to avoid function-call
72
+ * overhead. However, we have also found that the loop is faster than
73
+ * native libc memset() on some platforms, even those with assembler
74
+ * memset() functions. More research needs to be done, perhaps with
75
+ * MEMSET_LOOP_LIMIT tests in configure.
76
+ */
77
+ #define MemSet(start, val, len) \
78
+ do \
79
+ { \
80
+ /* must be void* because we don't know if it is integer aligned yet */ \
81
+ void *_vstart = (void *) (start); \
82
+ int _val = (val); \
83
+ Size _len = (len); \
84
+ \
85
+ if ((((intptr_t) _vstart) & LONG_ALIGN_MASK) == 0 && \
86
+ (_len & LONG_ALIGN_MASK) == 0 && \
87
+ _val == 0 && \
88
+ _len <= MEMSET_LOOP_LIMIT && \
89
+ /* \
90
+ * If MEMSET_LOOP_LIMIT == 0, optimizer should find \
91
+ * the whole "if" false at compile time. \
92
+ */ \
93
+ MEMSET_LOOP_LIMIT != 0) \
94
+ { \
95
+ long *_start = (long *) _vstart; \
96
+ long *_stop = (long *) ((char *) _start + _len); \
97
+ while (_start < _stop) \
98
+ *_start++ = 0; \
99
+ } \
100
+ else \
101
+ memset(_vstart, _val, _len); \
102
+ } while (0)
103
+
104
+ /*
105
+ * SNPRINTF, VSNPRINTF and friends
106
+ *
107
+ * These versions have been grabbed off the net. They have been
108
+ * cleaned up to compile properly and support for most of the Single Unix
109
+ * Specification has been added. Remaining unimplemented features are:
110
+ *
111
+ * 1. No locale support: the radix character is always '.' and the '
112
+ * (single quote) format flag is ignored.
113
+ *
114
+ * 2. No support for the "%n" format specification.
115
+ *
116
+ * 3. No support for wide characters ("lc" and "ls" formats).
117
+ *
118
+ * 4. No support for "long double" ("Lf" and related formats).
119
+ *
120
+ * 5. Space and '#' flags are not implemented.
121
+ *
122
+ *
123
+ * The result values of these functions are not the same across different
124
+ * platforms. This implementation is compatible with the Single Unix Spec:
125
+ *
126
+ * 1. -1 is returned only if processing is abandoned due to an invalid
127
+ * parameter, such as incorrect format string. (Although not required by
128
+ * the spec, this happens only when no characters have yet been transmitted
129
+ * to the destination.)
130
+ *
131
+ * 2. For snprintf and sprintf, 0 is returned if str == NULL or count == 0;
132
+ * no data has been stored.
133
+ *
134
+ * 3. Otherwise, the number of bytes actually transmitted to the destination
135
+ * is returned (excluding the trailing '\0' for snprintf and sprintf).
136
+ *
137
+ * For snprintf with nonzero count, the result cannot be more than count-1
138
+ * (a trailing '\0' is always stored); it is not possible to distinguish
139
+ * buffer overrun from exact fit. This is unlike some implementations that
140
+ * return the number of bytes that would have been needed for the complete
141
+ * result string.
142
+ */
143
+
144
+ /**************************************************************
145
+ * Original:
146
+ * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
147
+ * A bombproof version of doprnt (dopr) included.
148
+ * Sigh. This sort of thing is always nasty do deal with. Note that
149
+ * the version here does not include floating point. (now it does ... tgl)
150
+ **************************************************************/
151
+
152
+ /* Prevent recursion */
153
+ #undef vsnprintf
154
+ #undef snprintf
155
+ #undef sprintf
156
+ #undef vfprintf
157
+ #undef fprintf
158
+ #undef printf
159
+
160
+ /* Info about where the formatted output is going */
161
+ typedef struct
162
+ {
163
+ char *bufptr; /* next buffer output position */
164
+ char *bufstart; /* first buffer element */
165
+ char *bufend; /* last buffer element, or NULL */
166
+ /* bufend == NULL is for sprintf, where we assume buf is big enough */
167
+ FILE *stream; /* eventual output destination, or NULL */
168
+ int nchars; /* # chars already sent to stream */
169
+ } PrintfTarget;
170
+
171
+ /*
172
+ * Info about the type and value of a formatting parameter. Note that we
173
+ * don't currently support "long double", "wint_t", or "wchar_t *" data,
174
+ * nor the '%n' formatting code; else we'd need more types. Also, at this
175
+ * level we need not worry about signed vs unsigned values.
176
+ */
177
+ typedef enum
178
+ {
179
+ ATYPE_NONE = 0,
180
+ ATYPE_INT,
181
+ ATYPE_LONG,
182
+ ATYPE_LONGLONG,
183
+ ATYPE_DOUBLE,
184
+ ATYPE_CHARPTR
185
+ } PrintfArgType;
186
+
187
+ typedef union
188
+ {
189
+ int i;
190
+ long l;
191
+ int64 ll;
192
+ double d;
193
+ char *cptr;
194
+ } PrintfArgValue;
195
+
196
+
197
+ static void flushbuffer(PrintfTarget *target);
198
+ static int dopr(PrintfTarget *target, const char *format, va_list args);
199
+
200
+
201
+ int
202
+ pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
203
+ {
204
+ PrintfTarget target;
205
+
206
+ if (str == NULL || count == 0)
207
+ return 0;
208
+ target.bufstart = target.bufptr = str;
209
+ target.bufend = str + count - 1;
210
+ target.stream = NULL;
211
+ /* target.nchars is unused in this case */
212
+ if (dopr(&target, fmt, args))
213
+ {
214
+ *(target.bufptr) = '\0';
215
+
216
+ errno = EINVAL; /* bad format */
217
+
218
+ return -1;
219
+ }
220
+ *(target.bufptr) = '\0';
221
+ return target.bufptr - target.bufstart;
222
+ }
223
+
224
+ #if 0
225
+ int
226
+ pg_snprintf(char *str, size_t count, const char *fmt,...)
227
+ {
228
+ int len;
229
+ va_list args;
230
+
231
+ va_start(args, fmt);
232
+ len = pg_vsnprintf(str, count, fmt, args);
233
+ va_end(args);
234
+ return len;
235
+ }
236
+
237
+ static int
238
+ pg_vsprintf(char *str, const char *fmt, va_list args)
239
+ {
240
+ PrintfTarget target;
241
+
242
+ if (str == NULL)
243
+ return 0;
244
+ target.bufstart = target.bufptr = str;
245
+ target.bufend = NULL;
246
+ target.stream = NULL;
247
+ /* target.nchars is unused in this case */
248
+ if (dopr(&target, fmt, args))
249
+ {
250
+ *(target.bufptr) = '\0';
251
+
252
+ errno = EINVAL; /* bad format */
253
+
254
+ return -1;
255
+ }
256
+ *(target.bufptr) = '\0';
257
+ return target.bufptr - target.bufstart;
258
+ }
259
+
260
+ int
261
+ pg_sprintf(char *str, const char *fmt,...)
262
+ {
263
+ int len;
264
+ va_list args;
265
+
266
+ va_start(args, fmt);
267
+ len = pg_vsprintf(str, fmt, args);
268
+ va_end(args);
269
+ return len;
270
+ }
271
+
272
+ int
273
+ pg_vfprintf(FILE *stream, const char *fmt, va_list args)
274
+ {
275
+ PrintfTarget target;
276
+ char buffer[1024]; /* size is arbitrary */
277
+
278
+ if (stream == NULL)
279
+ {
280
+ errno = EINVAL;
281
+ return -1;
282
+ }
283
+ target.bufstart = target.bufptr = buffer;
284
+ target.bufend = buffer + sizeof(buffer) - 1;
285
+ target.stream = stream;
286
+ target.nchars = 0;
287
+ if (dopr(&target, fmt, args))
288
+ {
289
+ errno = EINVAL; /* bad format */
290
+ return -1;
291
+ }
292
+ /* dump any remaining buffer contents */
293
+ flushbuffer(&target);
294
+ return target.nchars;
295
+ }
296
+
297
+ int
298
+ pg_fprintf(FILE *stream, const char *fmt,...)
299
+ {
300
+ int len;
301
+ va_list args;
302
+
303
+ va_start(args, fmt);
304
+ len = pg_vfprintf(stream, fmt, args);
305
+ va_end(args);
306
+ return len;
307
+ }
308
+
309
+ int
310
+ pg_printf(const char *fmt,...)
311
+ {
312
+ int len;
313
+ va_list args;
314
+
315
+ va_start(args, fmt);
316
+ len = pg_vfprintf(stdout, fmt, args);
317
+ va_end(args);
318
+ return len;
319
+ }
320
+ #endif
321
+
322
+ /* call this only when stream is defined */
323
+ static void
324
+ flushbuffer(PrintfTarget *target)
325
+ {
326
+ size_t nc = target->bufptr - target->bufstart;
327
+
328
+ if (nc > 0)
329
+ target->nchars += fwrite(target->bufstart, 1, nc, target->stream);
330
+ target->bufptr = target->bufstart;
331
+ }
332
+
333
+ static void fmtstr(char *value, int leftjust, int minlen, int maxwidth,
334
+ int pointflag, PrintfTarget *target);
335
+ static void fmtptr(void *value, PrintfTarget *target);
336
+ static void fmtint(int64 value, char type, int forcesign,
337
+ int leftjust, int minlen, int zpad, int precision, int pointflag,
338
+ PrintfTarget *target);
339
+ static void fmtchar(int value, int leftjust, int minlen, PrintfTarget *target);
340
+ static void fmtfloat(double value, char type, int forcesign,
341
+ int leftjust, int minlen, int zpad, int precision, int pointflag,
342
+ PrintfTarget *target);
343
+ static void dostr(const char *str, int slen, PrintfTarget *target);
344
+ static void dopr_outch(int c, PrintfTarget *target);
345
+ static int adjust_sign(int is_negative, int forcesign, int *signvalue);
346
+ static void adjust_padlen(int minlen, int vallen, int leftjust, int *padlen);
347
+ static void leading_pad(int zpad, int *signvalue, int *padlen,
348
+ PrintfTarget *target);
349
+ static void trailing_pad(int *padlen, PrintfTarget *target);
350
+
351
+ /*
352
+ * dopr(): poor man's version of doprintf
353
+ */
354
+ static int
355
+ dopr(PrintfTarget *target, const char *format, va_list args)
356
+ {
357
+ const char *format_start = format;
358
+ int ch;
359
+ bool have_dollar;
360
+ bool have_non_dollar;
361
+ bool have_star;
362
+ bool afterstar;
363
+ int accum;
364
+ int longlongflag;
365
+ int longflag;
366
+ int pointflag;
367
+ int leftjust;
368
+ int fieldwidth;
369
+ int precision;
370
+ int zpad;
371
+ int forcesign;
372
+ int last_dollar;
373
+ int fmtpos;
374
+ int cvalue;
375
+ int64 numvalue;
376
+ double fvalue;
377
+ char *strvalue;
378
+ int i;
379
+ PrintfArgType argtypes[NL_ARGMAX + 1];
380
+ PrintfArgValue argvalues[NL_ARGMAX + 1];
381
+
382
+ /*
383
+ * Parse the format string to determine whether there are %n$ format
384
+ * specs, and identify the types and order of the format parameters.
385
+ */
386
+ have_dollar = have_non_dollar = false;
387
+ last_dollar = 0;
388
+ MemSet(argtypes, 0, sizeof(argtypes));
389
+
390
+ while ((ch = *format++) != '\0')
391
+ {
392
+ if (ch != '%')
393
+ continue;
394
+ longflag = longlongflag = pointflag = 0;
395
+ fmtpos = accum = 0;
396
+ afterstar = false;
397
+ nextch1:
398
+ ch = *format++;
399
+ if (ch == '\0')
400
+ break; /* illegal, but we don't complain */
401
+ switch (ch)
402
+ {
403
+ case '-':
404
+ case '+':
405
+ goto nextch1;
406
+ case '0':
407
+ case '1':
408
+ case '2':
409
+ case '3':
410
+ case '4':
411
+ case '5':
412
+ case '6':
413
+ case '7':
414
+ case '8':
415
+ case '9':
416
+ accum = accum * 10 + (ch - '0');
417
+ goto nextch1;
418
+ case '.':
419
+ pointflag = 1;
420
+ accum = 0;
421
+ goto nextch1;
422
+ case '*':
423
+ if (afterstar)
424
+ have_non_dollar = true; /* multiple stars */
425
+ afterstar = true;
426
+ accum = 0;
427
+ goto nextch1;
428
+ case '$':
429
+ have_dollar = true;
430
+ if (accum <= 0 || accum > NL_ARGMAX)
431
+ return -1;
432
+ if (afterstar)
433
+ {
434
+ if (argtypes[accum] &&
435
+ argtypes[accum] != ATYPE_INT)
436
+ return -1;
437
+ argtypes[accum] = ATYPE_INT;
438
+ last_dollar = Max(last_dollar, accum);
439
+ afterstar = false;
440
+ }
441
+ else
442
+ fmtpos = accum;
443
+ accum = 0;
444
+ goto nextch1;
445
+ case 'l':
446
+ if (longflag)
447
+ longlongflag = 1;
448
+ else
449
+ longflag = 1;
450
+ goto nextch1;
451
+ case 'h':
452
+ case '\'':
453
+ /* ignore these */
454
+ goto nextch1;
455
+ case 'd':
456
+ case 'i':
457
+ case 'o':
458
+ case 'u':
459
+ case 'x':
460
+ case 'X':
461
+ if (fmtpos)
462
+ {
463
+ PrintfArgType atype;
464
+
465
+ if (longlongflag)
466
+ atype = ATYPE_LONGLONG;
467
+ else if (longflag)
468
+ atype = ATYPE_LONG;
469
+ else
470
+ atype = ATYPE_INT;
471
+ if (argtypes[fmtpos] &&
472
+ argtypes[fmtpos] != atype)
473
+ return -1;
474
+ argtypes[fmtpos] = atype;
475
+ last_dollar = Max(last_dollar, fmtpos);
476
+ }
477
+ else
478
+ have_non_dollar = true;
479
+ break;
480
+ case 'c':
481
+ if (fmtpos)
482
+ {
483
+ if (argtypes[fmtpos] &&
484
+ argtypes[fmtpos] != ATYPE_INT)
485
+ return -1;
486
+ argtypes[fmtpos] = ATYPE_INT;
487
+ last_dollar = Max(last_dollar, fmtpos);
488
+ }
489
+ else
490
+ have_non_dollar = true;
491
+ break;
492
+ case 's':
493
+ case 'p':
494
+ if (fmtpos)
495
+ {
496
+ if (argtypes[fmtpos] &&
497
+ argtypes[fmtpos] != ATYPE_CHARPTR)
498
+ return -1;
499
+ argtypes[fmtpos] = ATYPE_CHARPTR;
500
+ last_dollar = Max(last_dollar, fmtpos);
501
+ }
502
+ else
503
+ have_non_dollar = true;
504
+ break;
505
+ case 'e':
506
+ case 'E':
507
+ case 'f':
508
+ case 'g':
509
+ case 'G':
510
+ if (fmtpos)
511
+ {
512
+ if (argtypes[fmtpos] &&
513
+ argtypes[fmtpos] != ATYPE_DOUBLE)
514
+ return -1;
515
+ argtypes[fmtpos] = ATYPE_DOUBLE;
516
+ last_dollar = Max(last_dollar, fmtpos);
517
+ }
518
+ else
519
+ have_non_dollar = true;
520
+ break;
521
+ case '%':
522
+ break;
523
+ }
524
+
525
+ /*
526
+ * If we finish the spec with afterstar still set, there's a
527
+ * non-dollar star in there.
528
+ */
529
+ if (afterstar)
530
+ have_non_dollar = true;
531
+ }
532
+
533
+ /* Per spec, you use either all dollar or all not. */
534
+ if (have_dollar && have_non_dollar)
535
+ return -1;
536
+
537
+ /*
538
+ * In dollar mode, collect the arguments in physical order.
539
+ */
540
+ for (i = 1; i <= last_dollar; i++)
541
+ {
542
+ switch (argtypes[i])
543
+ {
544
+ case ATYPE_NONE:
545
+ return -1; /* invalid format */
546
+ case ATYPE_INT:
547
+ argvalues[i].i = va_arg(args, int);
548
+ break;
549
+ case ATYPE_LONG:
550
+ argvalues[i].l = va_arg(args, long);
551
+ break;
552
+ case ATYPE_LONGLONG:
553
+ argvalues[i].ll = va_arg(args, int64);
554
+ break;
555
+ case ATYPE_DOUBLE:
556
+ argvalues[i].d = va_arg(args, double);
557
+ break;
558
+ case ATYPE_CHARPTR:
559
+ argvalues[i].cptr = va_arg(args, char *);
560
+ break;
561
+ }
562
+ }
563
+
564
+ /*
565
+ * At last we can parse the format for real.
566
+ */
567
+ format = format_start;
568
+ while ((ch = *format++) != '\0')
569
+ {
570
+ if (ch != '%')
571
+ {
572
+ dopr_outch(ch, target);
573
+ continue;
574
+ }
575
+ fieldwidth = precision = zpad = leftjust = forcesign = 0;
576
+ longflag = longlongflag = pointflag = 0;
577
+ fmtpos = accum = 0;
578
+ have_star = afterstar = false;
579
+ nextch2:
580
+ ch = *format++;
581
+ if (ch == '\0')
582
+ break; /* illegal, but we don't complain */
583
+ switch (ch)
584
+ {
585
+ case '-':
586
+ leftjust = 1;
587
+ goto nextch2;
588
+ case '+':
589
+ forcesign = 1;
590
+ goto nextch2;
591
+ case '0':
592
+ /* set zero padding if no nonzero digits yet */
593
+ if (accum == 0 && !pointflag)
594
+ zpad = '0';
595
+ /* FALL THRU */
596
+ case '1':
597
+ case '2':
598
+ case '3':
599
+ case '4':
600
+ case '5':
601
+ case '6':
602
+ case '7':
603
+ case '8':
604
+ case '9':
605
+ accum = accum * 10 + (ch - '0');
606
+ goto nextch2;
607
+ case '.':
608
+ if (have_star)
609
+ have_star = false;
610
+ else
611
+ fieldwidth = accum;
612
+ pointflag = 1;
613
+ accum = 0;
614
+ goto nextch2;
615
+ case '*':
616
+ if (have_dollar)
617
+ {
618
+ /* process value after reading n$ */
619
+ afterstar = true;
620
+ }
621
+ else
622
+ {
623
+ /* fetch and process value now */
624
+ int starval = va_arg(args, int);
625
+
626
+ if (pointflag)
627
+ {
628
+ precision = starval;
629
+ if (precision < 0)
630
+ {
631
+ precision = 0;
632
+ pointflag = 0;
633
+ }
634
+ }
635
+ else
636
+ {
637
+ fieldwidth = starval;
638
+ if (fieldwidth < 0)
639
+ {
640
+ leftjust = 1;
641
+ fieldwidth = -fieldwidth;
642
+ }
643
+ }
644
+ }
645
+ have_star = true;
646
+ accum = 0;
647
+ goto nextch2;
648
+ case '$':
649
+ if (afterstar)
650
+ {
651
+ /* fetch and process star value */
652
+ int starval = argvalues[accum].i;
653
+
654
+ if (pointflag)
655
+ {
656
+ precision = starval;
657
+ if (precision < 0)
658
+ {
659
+ precision = 0;
660
+ pointflag = 0;
661
+ }
662
+ }
663
+ else
664
+ {
665
+ fieldwidth = starval;
666
+ if (fieldwidth < 0)
667
+ {
668
+ leftjust = 1;
669
+ fieldwidth = -fieldwidth;
670
+ }
671
+ }
672
+ afterstar = false;
673
+ }
674
+ else
675
+ fmtpos = accum;
676
+ accum = 0;
677
+ goto nextch2;
678
+ case 'l':
679
+ if (longflag)
680
+ longlongflag = 1;
681
+ else
682
+ longflag = 1;
683
+ goto nextch2;
684
+ case 'h':
685
+ case '\'':
686
+ /* ignore these */
687
+ goto nextch2;
688
+ case 'd':
689
+ case 'i':
690
+ if (!have_star)
691
+ {
692
+ if (pointflag)
693
+ precision = accum;
694
+ else
695
+ fieldwidth = accum;
696
+ }
697
+ if (have_dollar)
698
+ {
699
+ if (longlongflag)
700
+ numvalue = argvalues[fmtpos].ll;
701
+ else if (longflag)
702
+ numvalue = argvalues[fmtpos].l;
703
+ else
704
+ numvalue = argvalues[fmtpos].i;
705
+ }
706
+ else
707
+ {
708
+ if (longlongflag)
709
+ numvalue = va_arg(args, int64);
710
+ else if (longflag)
711
+ numvalue = va_arg(args, long);
712
+ else
713
+ numvalue = va_arg(args, int);
714
+ }
715
+ fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
716
+ precision, pointflag, target);
717
+ break;
718
+ case 'o':
719
+ case 'u':
720
+ case 'x':
721
+ case 'X':
722
+ if (!have_star)
723
+ {
724
+ if (pointflag)
725
+ precision = accum;
726
+ else
727
+ fieldwidth = accum;
728
+ }
729
+ if (have_dollar)
730
+ {
731
+ if (longlongflag)
732
+ numvalue = (uint64) argvalues[fmtpos].ll;
733
+ else if (longflag)
734
+ numvalue = (unsigned long) argvalues[fmtpos].l;
735
+ else
736
+ numvalue = (unsigned int) argvalues[fmtpos].i;
737
+ }
738
+ else
739
+ {
740
+ if (longlongflag)
741
+ numvalue = (uint64) va_arg(args, int64);
742
+ else if (longflag)
743
+ numvalue = (unsigned long) va_arg(args, long);
744
+ else
745
+ numvalue = (unsigned int) va_arg(args, int);
746
+ }
747
+ fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
748
+ precision, pointflag, target);
749
+ break;
750
+ case 'c':
751
+ if (!have_star)
752
+ {
753
+ if (pointflag)
754
+ precision = accum;
755
+ else
756
+ fieldwidth = accum;
757
+ }
758
+ if (have_dollar)
759
+ cvalue = (unsigned char) argvalues[fmtpos].i;
760
+ else
761
+ cvalue = (unsigned char) va_arg(args, int);
762
+ fmtchar(cvalue, leftjust, fieldwidth, target);
763
+ break;
764
+ case 's':
765
+ if (!have_star)
766
+ {
767
+ if (pointflag)
768
+ precision = accum;
769
+ else
770
+ fieldwidth = accum;
771
+ }
772
+ if (have_dollar)
773
+ strvalue = argvalues[fmtpos].cptr;
774
+ else
775
+ strvalue = va_arg(args, char *);
776
+ fmtstr(strvalue, leftjust, fieldwidth, precision, pointflag,
777
+ target);
778
+ break;
779
+ case 'p':
780
+ /* fieldwidth/leftjust are ignored ... */
781
+ if (have_dollar)
782
+ strvalue = argvalues[fmtpos].cptr;
783
+ else
784
+ strvalue = va_arg(args, char *);
785
+ fmtptr((void *) strvalue, target);
786
+ break;
787
+ case 'e':
788
+ case 'E':
789
+ case 'f':
790
+ case 'g':
791
+ case 'G':
792
+ if (!have_star)
793
+ {
794
+ if (pointflag)
795
+ precision = accum;
796
+ else
797
+ fieldwidth = accum;
798
+ }
799
+ if (have_dollar)
800
+ fvalue = argvalues[fmtpos].d;
801
+ else
802
+ fvalue = va_arg(args, double);
803
+ fmtfloat(fvalue, ch, forcesign, leftjust,
804
+ fieldwidth, zpad,
805
+ precision, pointflag,
806
+ target);
807
+ break;
808
+ case '%':
809
+ dopr_outch('%', target);
810
+ break;
811
+ }
812
+ }
813
+
814
+ return 0;
815
+ }
816
+
817
+ static size_t
818
+ pg_strnlen(const char *str, size_t maxlen)
819
+ {
820
+ const char *p = str;
821
+
822
+ while (maxlen-- > 0 && *p)
823
+ p++;
824
+ return p - str;
825
+ }
826
+
827
+ static void
828
+ fmtstr(char *value, int leftjust, int minlen, int maxwidth,
829
+ int pointflag, PrintfTarget *target)
830
+ {
831
+ int padlen,
832
+ vallen; /* amount to pad */
833
+
834
+ /*
835
+ * If a maxwidth (precision) is specified, we must not fetch more bytes
836
+ * than that.
837
+ */
838
+ if (pointflag)
839
+ vallen = pg_strnlen(value, maxwidth);
840
+ else
841
+ vallen = strlen(value);
842
+
843
+ adjust_padlen(minlen, vallen, leftjust, &padlen);
844
+
845
+ while (padlen > 0)
846
+ {
847
+ dopr_outch(' ', target);
848
+ --padlen;
849
+ }
850
+
851
+ dostr(value, vallen, target);
852
+
853
+ trailing_pad(&padlen, target);
854
+ }
855
+
856
+ static void
857
+ fmtptr(void *value, PrintfTarget *target)
858
+ {
859
+ int vallen;
860
+ char convert[64];
861
+
862
+ /* we rely on regular C library's sprintf to do the basic conversion */
863
+ vallen = sprintf(convert, "%p", value);
864
+
865
+ dostr(convert, vallen, target);
866
+ }
867
+
868
+ static void
869
+ fmtint(int64 value, char type, int forcesign, int leftjust,
870
+ int minlen, int zpad, int precision, int pointflag,
871
+ PrintfTarget *target)
872
+ {
873
+ uint64 base;
874
+ int dosign;
875
+ const char *cvt = "0123456789abcdef";
876
+ int signvalue = 0;
877
+ char convert[64];
878
+ int vallen = 0;
879
+ int padlen = 0; /* amount to pad */
880
+ int zeropad; /* extra leading zeroes */
881
+
882
+ switch (type)
883
+ {
884
+ case 'd':
885
+ case 'i':
886
+ base = 10;
887
+ dosign = 1;
888
+ break;
889
+ case 'o':
890
+ base = 8;
891
+ dosign = 0;
892
+ break;
893
+ case 'u':
894
+ base = 10;
895
+ dosign = 0;
896
+ break;
897
+ case 'x':
898
+ base = 16;
899
+ dosign = 0;
900
+ break;
901
+ case 'X':
902
+ cvt = "0123456789ABCDEF";
903
+ base = 16;
904
+ dosign = 0;
905
+ break;
906
+ default:
907
+ return; /* keep compiler quiet */
908
+ }
909
+
910
+ /* Handle +/- */
911
+ if (dosign && adjust_sign((value < 0), forcesign, &signvalue))
912
+ value = -value;
913
+
914
+ /*
915
+ * SUS: the result of converting 0 with an explicit precision of 0 is no
916
+ * characters
917
+ */
918
+ if (value == 0 && pointflag && precision == 0)
919
+ vallen = 0;
920
+ else
921
+ {
922
+ /* make integer string */
923
+ uint64 uvalue = (uint64) value;
924
+
925
+ do
926
+ {
927
+ convert[vallen++] = cvt[uvalue % base];
928
+ uvalue = uvalue / base;
929
+ } while (uvalue);
930
+ }
931
+
932
+ zeropad = Max(0, precision - vallen);
933
+
934
+ adjust_padlen(minlen, vallen + zeropad, leftjust, &padlen);
935
+
936
+ leading_pad(zpad, &signvalue, &padlen, target);
937
+
938
+ while (zeropad-- > 0)
939
+ dopr_outch('0', target);
940
+
941
+ while (vallen > 0)
942
+ dopr_outch(convert[--vallen], target);
943
+
944
+ trailing_pad(&padlen, target);
945
+ }
946
+
947
+ static void
948
+ fmtchar(int value, int leftjust, int minlen, PrintfTarget *target)
949
+ {
950
+ int padlen = 0; /* amount to pad */
951
+
952
+ adjust_padlen(minlen, 1, leftjust, &padlen);
953
+
954
+ while (padlen > 0)
955
+ {
956
+ dopr_outch(' ', target);
957
+ --padlen;
958
+ }
959
+
960
+ dopr_outch(value, target);
961
+
962
+ trailing_pad(&padlen, target);
963
+ }
964
+
965
+ static void
966
+ fmtfloat(double value, char type, int forcesign, int leftjust,
967
+ int minlen, int zpad, int precision, int pointflag,
968
+ PrintfTarget *target)
969
+ {
970
+ int signvalue = 0;
971
+ int vallen;
972
+ char fmt[32];
973
+ char convert[512];
974
+ int padlen = 0; /* amount to pad */
975
+
976
+ /* we rely on regular C library's sprintf to do the basic conversion */
977
+ if (pointflag)
978
+ sprintf(fmt, "%%.%d%c", precision, type);
979
+ else
980
+ sprintf(fmt, "%%%c", type);
981
+
982
+ if (adjust_sign((value < 0), forcesign, &signvalue))
983
+ value = -value;
984
+
985
+ vallen = sprintf(convert, fmt, value);
986
+
987
+ adjust_padlen(minlen, vallen, leftjust, &padlen);
988
+
989
+ leading_pad(zpad, &signvalue, &padlen, target);
990
+
991
+ dostr(convert, vallen, target);
992
+
993
+ trailing_pad(&padlen, target);
994
+ }
995
+
996
+ static void
997
+ dostr(const char *str, int slen, PrintfTarget *target)
998
+ {
999
+ while (slen > 0)
1000
+ {
1001
+ int avail;
1002
+
1003
+ if (target->bufend != NULL)
1004
+ avail = target->bufend - target->bufptr;
1005
+ else
1006
+ avail = slen;
1007
+ if (avail <= 0)
1008
+ {
1009
+ /* buffer full, can we dump to stream? */
1010
+ if (target->stream == NULL)
1011
+ return; /* no, lose the data */
1012
+ flushbuffer(target);
1013
+ continue;
1014
+ }
1015
+ avail = Min(avail, slen);
1016
+ memmove(target->bufptr, str, avail);
1017
+ target->bufptr += avail;
1018
+ str += avail;
1019
+ slen -= avail;
1020
+ }
1021
+ }
1022
+
1023
+ static void
1024
+ dopr_outch(int c, PrintfTarget *target)
1025
+ {
1026
+ if (target->bufend != NULL && target->bufptr >= target->bufend)
1027
+ {
1028
+ /* buffer full, can we dump to stream? */
1029
+ if (target->stream == NULL)
1030
+ return; /* no, lose the data */
1031
+ flushbuffer(target);
1032
+ }
1033
+ *(target->bufptr++) = c;
1034
+ }
1035
+
1036
+ static int
1037
+ adjust_sign(int is_negative, int forcesign, int *signvalue)
1038
+ {
1039
+ if (is_negative)
1040
+ {
1041
+ *signvalue = '-';
1042
+ return true;
1043
+ }
1044
+ else if (forcesign)
1045
+ *signvalue = '+';
1046
+ return false;
1047
+ }
1048
+
1049
+
1050
+ static void
1051
+ adjust_padlen(int minlen, int vallen, int leftjust, int *padlen)
1052
+ {
1053
+ *padlen = minlen - vallen;
1054
+ if (*padlen < 0)
1055
+ *padlen = 0;
1056
+ if (leftjust)
1057
+ *padlen = -(*padlen);
1058
+ }
1059
+
1060
+
1061
+ static void
1062
+ leading_pad(int zpad, int *signvalue, int *padlen, PrintfTarget *target)
1063
+ {
1064
+ if (*padlen > 0 && zpad)
1065
+ {
1066
+ if (*signvalue)
1067
+ {
1068
+ dopr_outch(*signvalue, target);
1069
+ --(*padlen);
1070
+ *signvalue = 0;
1071
+ }
1072
+ while (*padlen > 0)
1073
+ {
1074
+ dopr_outch(zpad, target);
1075
+ --(*padlen);
1076
+ }
1077
+ }
1078
+ while (*padlen > (*signvalue != 0))
1079
+ {
1080
+ dopr_outch(' ', target);
1081
+ --(*padlen);
1082
+ }
1083
+ if (*signvalue)
1084
+ {
1085
+ dopr_outch(*signvalue, target);
1086
+ if (*padlen > 0)
1087
+ --(*padlen);
1088
+ else if (*padlen < 0)
1089
+ ++(*padlen);
1090
+ }
1091
+ }
1092
+
1093
+
1094
+ static void
1095
+ trailing_pad(int *padlen, PrintfTarget *target)
1096
+ {
1097
+ while (*padlen < 0)
1098
+ {
1099
+ dopr_outch(' ', target);
1100
+ ++(*padlen);
1101
+ }
1102
+ }