remind-rb 6.2.10.1

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 (658) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +328 -0
  3. data/README.md +141 -0
  4. data/ext/remind/shim.c +379 -0
  5. data/lib/remind/builder.rb +252 -0
  6. data/lib/remind/library.rb +141 -0
  7. data/lib/remind/native.rb +257 -0
  8. data/lib/remind/reminder.rb +527 -0
  9. data/lib/remind/runtime.rb +130 -0
  10. data/lib/remind/session.rb +246 -0
  11. data/lib/remind/source.rb +160 -0
  12. data/lib/remind/value.rb +170 -0
  13. data/lib/remind/version.rb +13 -0
  14. data/lib/remind.rb +147 -0
  15. data/remind-v06.02.10/COPYRIGHT +300 -0
  16. data/remind-v06.02.10/configure +5684 -0
  17. data/remind-v06.02.10/configure.ac +131 -0
  18. data/remind-v06.02.10/docs/WHATSNEW +3858 -0
  19. data/remind-v06.02.10/include/ansitext.rem +35 -0
  20. data/remind-v06.02.10/include/holidays/ad/02.rem +15 -0
  21. data/remind-v06.02.10/include/holidays/ad/03.rem +14 -0
  22. data/remind-v06.02.10/include/holidays/ad/04.rem +14 -0
  23. data/remind-v06.02.10/include/holidays/ad/05.rem +14 -0
  24. data/remind-v06.02.10/include/holidays/ad/06.rem +16 -0
  25. data/remind-v06.02.10/include/holidays/ad/07.rem +15 -0
  26. data/remind-v06.02.10/include/holidays/ad/08.rem +14 -0
  27. data/remind-v06.02.10/include/holidays/ad.rem +28 -0
  28. data/remind-v06.02.10/include/holidays/ae.rem +10 -0
  29. data/remind-v06.02.10/include/holidays/al.rem +33 -0
  30. data/remind-v06.02.10/include/holidays/am.rem +19 -0
  31. data/remind-v06.02.10/include/holidays/ao.rem +41 -0
  32. data/remind-v06.02.10/include/holidays/ar.rem +38 -0
  33. data/remind-v06.02.10/include/holidays/as.rem +40 -0
  34. data/remind-v06.02.10/include/holidays/at/1.rem +15 -0
  35. data/remind-v06.02.10/include/holidays/at/2.rem +16 -0
  36. data/remind-v06.02.10/include/holidays/at/3.rem +15 -0
  37. data/remind-v06.02.10/include/holidays/at/4.rem +15 -0
  38. data/remind-v06.02.10/include/holidays/at/5.rem +15 -0
  39. data/remind-v06.02.10/include/holidays/at/6.rem +15 -0
  40. data/remind-v06.02.10/include/holidays/at/7.rem +15 -0
  41. data/remind-v06.02.10/include/holidays/at/8.rem +15 -0
  42. data/remind-v06.02.10/include/holidays/at/9.rem +15 -0
  43. data/remind-v06.02.10/include/holidays/at.rem +32 -0
  44. data/remind-v06.02.10/include/holidays/au/act.rem +27 -0
  45. data/remind-v06.02.10/include/holidays/au/nsw.rem +25 -0
  46. data/remind-v06.02.10/include/holidays/au/nt.rem +28 -0
  47. data/remind-v06.02.10/include/holidays/au/qld.rem +23 -0
  48. data/remind-v06.02.10/include/holidays/au/sa.rem +29 -0
  49. data/remind-v06.02.10/include/holidays/au/tas.rem +16 -0
  50. data/remind-v06.02.10/include/holidays/au/vic.rem +24 -0
  51. data/remind-v06.02.10/include/holidays/au/wa.rem +24 -0
  52. data/remind-v06.02.10/include/holidays/au.rem +21 -0
  53. data/remind-v06.02.10/include/holidays/aw.rem +19 -0
  54. data/remind-v06.02.10/include/holidays/az.rem +44 -0
  55. data/remind-v06.02.10/include/holidays/ba/bih.rem +23 -0
  56. data/remind-v06.02.10/include/holidays/ba/brc.rem +20 -0
  57. data/remind-v06.02.10/include/holidays/ba/srp.rem +23 -0
  58. data/remind-v06.02.10/include/holidays/ba.rem +22 -0
  59. data/remind-v06.02.10/include/holidays/bb.rem +28 -0
  60. data/remind-v06.02.10/include/holidays/bd.rem +14 -0
  61. data/remind-v06.02.10/include/holidays/be.rem +24 -0
  62. data/remind-v06.02.10/include/holidays/bf.rem +29 -0
  63. data/remind-v06.02.10/include/holidays/bg.rem +34 -0
  64. data/remind-v06.02.10/include/holidays/bh.rem +11 -0
  65. data/remind-v06.02.10/include/holidays/bi.rem +30 -0
  66. data/remind-v06.02.10/include/holidays/bn.rem +22 -0
  67. data/remind-v06.02.10/include/holidays/bo/b.rem +13 -0
  68. data/remind-v06.02.10/include/holidays/bo/c.rem +13 -0
  69. data/remind-v06.02.10/include/holidays/bo/h.rem +13 -0
  70. data/remind-v06.02.10/include/holidays/bo/l.rem +13 -0
  71. data/remind-v06.02.10/include/holidays/bo/n.rem +13 -0
  72. data/remind-v06.02.10/include/holidays/bo/o.rem +13 -0
  73. data/remind-v06.02.10/include/holidays/bo/p.rem +13 -0
  74. data/remind-v06.02.10/include/holidays/bo/s.rem +13 -0
  75. data/remind-v06.02.10/include/holidays/bo/t.rem +13 -0
  76. data/remind-v06.02.10/include/holidays/bo.rem +32 -0
  77. data/remind-v06.02.10/include/holidays/br/ac.rem +21 -0
  78. data/remind-v06.02.10/include/holidays/br/al.rem +16 -0
  79. data/remind-v06.02.10/include/holidays/br/am.rem +13 -0
  80. data/remind-v06.02.10/include/holidays/br/ap.rem +15 -0
  81. data/remind-v06.02.10/include/holidays/br/ba.rem +13 -0
  82. data/remind-v06.02.10/include/holidays/br/ce.rem +15 -0
  83. data/remind-v06.02.10/include/holidays/br/df.rem +14 -0
  84. data/remind-v06.02.10/include/holidays/br/es.rem +13 -0
  85. data/remind-v06.02.10/include/holidays/br/go.rem +14 -0
  86. data/remind-v06.02.10/include/holidays/br/ma.rem +13 -0
  87. data/remind-v06.02.10/include/holidays/br/mg.rem +13 -0
  88. data/remind-v06.02.10/include/holidays/br/ms.rem +13 -0
  89. data/remind-v06.02.10/include/holidays/br/pa.rem +13 -0
  90. data/remind-v06.02.10/include/holidays/br/pb.rem +13 -0
  91. data/remind-v06.02.10/include/holidays/br/pe.rem +13 -0
  92. data/remind-v06.02.10/include/holidays/br/pi.rem +13 -0
  93. data/remind-v06.02.10/include/holidays/br/pr.rem +13 -0
  94. data/remind-v06.02.10/include/holidays/br/rj.rem +13 -0
  95. data/remind-v06.02.10/include/holidays/br/rn.rem +14 -0
  96. data/remind-v06.02.10/include/holidays/br/ro.rem +14 -0
  97. data/remind-v06.02.10/include/holidays/br/rr.rem +13 -0
  98. data/remind-v06.02.10/include/holidays/br/rs.rem +13 -0
  99. data/remind-v06.02.10/include/holidays/br/sc.rem +14 -0
  100. data/remind-v06.02.10/include/holidays/br/se.rem +13 -0
  101. data/remind-v06.02.10/include/holidays/br/sp.rem +13 -0
  102. data/remind-v06.02.10/include/holidays/br/to.rem +15 -0
  103. data/remind-v06.02.10/include/holidays/br.rem +33 -0
  104. data/remind-v06.02.10/include/holidays/bs.rem +26 -0
  105. data/remind-v06.02.10/include/holidays/bw.rem +31 -0
  106. data/remind-v06.02.10/include/holidays/by.rem +17 -0
  107. data/remind-v06.02.10/include/holidays/bz.rem +43 -0
  108. data/remind-v06.02.10/include/holidays/ca/ab.rem +17 -0
  109. data/remind-v06.02.10/include/holidays/ca/bc.rem +14 -0
  110. data/remind-v06.02.10/include/holidays/ca/mb.rem +16 -0
  111. data/remind-v06.02.10/include/holidays/ca/nb.rem +14 -0
  112. data/remind-v06.02.10/include/holidays/ca/nl.rem +19 -0
  113. data/remind-v06.02.10/include/holidays/ca/ns.rem +16 -0
  114. data/remind-v06.02.10/include/holidays/ca/nt.rem +14 -0
  115. data/remind-v06.02.10/include/holidays/ca/nu.rem +16 -0
  116. data/remind-v06.02.10/include/holidays/ca/on.rem +16 -0
  117. data/remind-v06.02.10/include/holidays/ca/pe.rem +13 -0
  118. data/remind-v06.02.10/include/holidays/ca/qc.rem +18 -0
  119. data/remind-v06.02.10/include/holidays/ca/sk.rem +14 -0
  120. data/remind-v06.02.10/include/holidays/ca/yt.rem +17 -0
  121. data/remind-v06.02.10/include/holidays/ca.rem +37 -0
  122. data/remind-v06.02.10/include/holidays/cg.rem +17 -0
  123. data/remind-v06.02.10/include/holidays/ch/ag.rem +22 -0
  124. data/remind-v06.02.10/include/holidays/ch/ai.rem +20 -0
  125. data/remind-v06.02.10/include/holidays/ch/ar.rem +16 -0
  126. data/remind-v06.02.10/include/holidays/ch/be.rem +17 -0
  127. data/remind-v06.02.10/include/holidays/ch/bl.rem +17 -0
  128. data/remind-v06.02.10/include/holidays/ch/bs.rem +17 -0
  129. data/remind-v06.02.10/include/holidays/ch/fr.rem +19 -0
  130. data/remind-v06.02.10/include/holidays/ch/ge.rem +17 -0
  131. data/remind-v06.02.10/include/holidays/ch/gl.rem +22 -0
  132. data/remind-v06.02.10/include/holidays/ch/gr.rem +18 -0
  133. data/remind-v06.02.10/include/holidays/ch/ju.rem +21 -0
  134. data/remind-v06.02.10/include/holidays/ch/lu.rem +21 -0
  135. data/remind-v06.02.10/include/holidays/ch/ne.rem +18 -0
  136. data/remind-v06.02.10/include/holidays/ch/nw.rem +24 -0
  137. data/remind-v06.02.10/include/holidays/ch/ow.rem +24 -0
  138. data/remind-v06.02.10/include/holidays/ch/sg.rem +20 -0
  139. data/remind-v06.02.10/include/holidays/ch/sh.rem +20 -0
  140. data/remind-v06.02.10/include/holidays/ch/so.rem +17 -0
  141. data/remind-v06.02.10/include/holidays/ch/sz.rem +22 -0
  142. data/remind-v06.02.10/include/holidays/ch/tg.rem +18 -0
  143. data/remind-v06.02.10/include/holidays/ch/ti.rem +23 -0
  144. data/remind-v06.02.10/include/holidays/ch/ur.rem +22 -0
  145. data/remind-v06.02.10/include/holidays/ch/vd.rem +17 -0
  146. data/remind-v06.02.10/include/holidays/ch/vs.rem +23 -0
  147. data/remind-v06.02.10/include/holidays/ch/zg.rem +23 -0
  148. data/remind-v06.02.10/include/holidays/ch/zh.rem +18 -0
  149. data/remind-v06.02.10/include/holidays/ch.rem +18 -0
  150. data/remind-v06.02.10/include/holidays/chinese-new-year.rem +86 -0
  151. data/remind-v06.02.10/include/holidays/cl/ap.rem +13 -0
  152. data/remind-v06.02.10/include/holidays/cl/nb.rem +13 -0
  153. data/remind-v06.02.10/include/holidays/cl.rem +46 -0
  154. data/remind-v06.02.10/include/holidays/cm.rem +21 -0
  155. data/remind-v06.02.10/include/holidays/co.rem +85 -0
  156. data/remind-v06.02.10/include/holidays/cr.rem +39 -0
  157. data/remind-v06.02.10/include/holidays/cu.rem +19 -0
  158. data/remind-v06.02.10/include/holidays/cw.rem +24 -0
  159. data/remind-v06.02.10/include/holidays/cy.rem +27 -0
  160. data/remind-v06.02.10/include/holidays/cz.rem +20 -0
  161. data/remind-v06.02.10/include/holidays/de/bb.rem +15 -0
  162. data/remind-v06.02.10/include/holidays/de/be.rem +13 -0
  163. data/remind-v06.02.10/include/holidays/de/bw.rem +15 -0
  164. data/remind-v06.02.10/include/holidays/de/by.rem +18 -0
  165. data/remind-v06.02.10/include/holidays/de/hb.rem +13 -0
  166. data/remind-v06.02.10/include/holidays/de/he.rem +13 -0
  167. data/remind-v06.02.10/include/holidays/de/hh.rem +13 -0
  168. data/remind-v06.02.10/include/holidays/de/mv.rem +14 -0
  169. data/remind-v06.02.10/include/holidays/de/ni.rem +13 -0
  170. data/remind-v06.02.10/include/holidays/de/nw.rem +14 -0
  171. data/remind-v06.02.10/include/holidays/de/rp.rem +14 -0
  172. data/remind-v06.02.10/include/holidays/de/sh.rem +13 -0
  173. data/remind-v06.02.10/include/holidays/de/sl.rem +15 -0
  174. data/remind-v06.02.10/include/holidays/de/sn.rem +14 -0
  175. data/remind-v06.02.10/include/holidays/de/st.rem +14 -0
  176. data/remind-v06.02.10/include/holidays/de/th.rem +14 -0
  177. data/remind-v06.02.10/include/holidays/de.rem +23 -0
  178. data/remind-v06.02.10/include/holidays/discordian.rem +25 -0
  179. data/remind-v06.02.10/include/holidays/dj.rem +12 -0
  180. data/remind-v06.02.10/include/holidays/dk.rem +23 -0
  181. data/remind-v06.02.10/include/holidays/dm.rem +24 -0
  182. data/remind-v06.02.10/include/holidays/do.rem +36 -0
  183. data/remind-v06.02.10/include/holidays/dz.rem +12 -0
  184. data/remind-v06.02.10/include/holidays/ec.rem +48 -0
  185. data/remind-v06.02.10/include/holidays/ee.rem +19 -0
  186. data/remind-v06.02.10/include/holidays/eg.rem +17 -0
  187. data/remind-v06.02.10/include/holidays/es/an.rem +17 -0
  188. data/remind-v06.02.10/include/holidays/es/ar.rem +17 -0
  189. data/remind-v06.02.10/include/holidays/es/as.rem +17 -0
  190. data/remind-v06.02.10/include/holidays/es/cb.rem +15 -0
  191. data/remind-v06.02.10/include/holidays/es/ce.rem +15 -0
  192. data/remind-v06.02.10/include/holidays/es/cl.rem +17 -0
  193. data/remind-v06.02.10/include/holidays/es/cm.rem +15 -0
  194. data/remind-v06.02.10/include/holidays/es/cn.rem +15 -0
  195. data/remind-v06.02.10/include/holidays/es/ct.rem +16 -0
  196. data/remind-v06.02.10/include/holidays/es/ex.rem +16 -0
  197. data/remind-v06.02.10/include/holidays/es/ga.rem +15 -0
  198. data/remind-v06.02.10/include/holidays/es/ib.rem +15 -0
  199. data/remind-v06.02.10/include/holidays/es/mc.rem +17 -0
  200. data/remind-v06.02.10/include/holidays/es/md.rem +16 -0
  201. data/remind-v06.02.10/include/holidays/es/ml.rem +15 -0
  202. data/remind-v06.02.10/include/holidays/es/nc.rem +15 -0
  203. data/remind-v06.02.10/include/holidays/es/pv.rem +15 -0
  204. data/remind-v06.02.10/include/holidays/es/ri.rem +16 -0
  205. data/remind-v06.02.10/include/holidays/es/vc.rem +16 -0
  206. data/remind-v06.02.10/include/holidays/es.rem +23 -0
  207. data/remind-v06.02.10/include/holidays/et.rem +20 -0
  208. data/remind-v06.02.10/include/holidays/fi.rem +43 -0
  209. data/remind-v06.02.10/include/holidays/fr/bl.rem +13 -0
  210. data/remind-v06.02.10/include/holidays/fr/ges.rem +14 -0
  211. data/remind-v06.02.10/include/holidays/fr/gp.rem +16 -0
  212. data/remind-v06.02.10/include/holidays/fr/gy.rem +13 -0
  213. data/remind-v06.02.10/include/holidays/fr/mf.rem +13 -0
  214. data/remind-v06.02.10/include/holidays/fr/mq.rem +15 -0
  215. data/remind-v06.02.10/include/holidays/fr/nc.rem +13 -0
  216. data/remind-v06.02.10/include/holidays/fr/pf.rem +15 -0
  217. data/remind-v06.02.10/include/holidays/fr/re.rem +13 -0
  218. data/remind-v06.02.10/include/holidays/fr/wf.rem +14 -0
  219. data/remind-v06.02.10/include/holidays/fr/yt.rem +13 -0
  220. data/remind-v06.02.10/include/holidays/fr.rem +18 -0
  221. data/remind-v06.02.10/include/holidays/ga.rem +18 -0
  222. data/remind-v06.02.10/include/holidays/gb/eng.rem +14 -0
  223. data/remind-v06.02.10/include/holidays/gb/nir.rem +20 -0
  224. data/remind-v06.02.10/include/holidays/gb/sct.rem +20 -0
  225. data/remind-v06.02.10/include/holidays/gb/wls.rem +14 -0
  226. data/remind-v06.02.10/include/holidays/gb.rem +27 -0
  227. data/remind-v06.02.10/include/holidays/ge.rem +24 -0
  228. data/remind-v06.02.10/include/holidays/gh.rem +34 -0
  229. data/remind-v06.02.10/include/holidays/gl.rem +25 -0
  230. data/remind-v06.02.10/include/holidays/gr.rem +37 -0
  231. data/remind-v06.02.10/include/holidays/gt.rem +24 -0
  232. data/remind-v06.02.10/include/holidays/gu.rem +37 -0
  233. data/remind-v06.02.10/include/holidays/hk.rem +25 -0
  234. data/remind-v06.02.10/include/holidays/hn.rem +18 -0
  235. data/remind-v06.02.10/include/holidays/hr.rem +21 -0
  236. data/remind-v06.02.10/include/holidays/ht.rem +34 -0
  237. data/remind-v06.02.10/include/holidays/hu.rem +20 -0
  238. data/remind-v06.02.10/include/holidays/id.rem +15 -0
  239. data/remind-v06.02.10/include/holidays/ie.rem +41 -0
  240. data/remind-v06.02.10/include/holidays/im.rem +26 -0
  241. data/remind-v06.02.10/include/holidays/in/ap.rem +14 -0
  242. data/remind-v06.02.10/include/holidays/in/as.rem +13 -0
  243. data/remind-v06.02.10/include/holidays/in/br.rem +14 -0
  244. data/remind-v06.02.10/include/holidays/in/cg.rem +13 -0
  245. data/remind-v06.02.10/include/holidays/in/gj.rem +15 -0
  246. data/remind-v06.02.10/include/holidays/in/hr.rem +14 -0
  247. data/remind-v06.02.10/include/holidays/in/ka.rem +13 -0
  248. data/remind-v06.02.10/include/holidays/in/kl.rem +14 -0
  249. data/remind-v06.02.10/include/holidays/in/mh.rem +15 -0
  250. data/remind-v06.02.10/include/holidays/in/mp.rem +13 -0
  251. data/remind-v06.02.10/include/holidays/in/od.rem +15 -0
  252. data/remind-v06.02.10/include/holidays/in/rj.rem +14 -0
  253. data/remind-v06.02.10/include/holidays/in/sk.rem +13 -0
  254. data/remind-v06.02.10/include/holidays/in/tn.rem +15 -0
  255. data/remind-v06.02.10/include/holidays/in/ts.rem +14 -0
  256. data/remind-v06.02.10/include/holidays/in/uk.rem +13 -0
  257. data/remind-v06.02.10/include/holidays/in/up.rem +13 -0
  258. data/remind-v06.02.10/include/holidays/in/wb.rem +16 -0
  259. data/remind-v06.02.10/include/holidays/in.rem +24 -0
  260. data/remind-v06.02.10/include/holidays/is.rem +23 -0
  261. data/remind-v06.02.10/include/holidays/it/ag.rem +13 -0
  262. data/remind-v06.02.10/include/holidays/it/al.rem +13 -0
  263. data/remind-v06.02.10/include/holidays/it/an.rem +13 -0
  264. data/remind-v06.02.10/include/holidays/it/andria.rem +13 -0
  265. data/remind-v06.02.10/include/holidays/it/ao.rem +13 -0
  266. data/remind-v06.02.10/include/holidays/it/ap.rem +13 -0
  267. data/remind-v06.02.10/include/holidays/it/aq.rem +13 -0
  268. data/remind-v06.02.10/include/holidays/it/ar.rem +13 -0
  269. data/remind-v06.02.10/include/holidays/it/at.rem +13 -0
  270. data/remind-v06.02.10/include/holidays/it/av.rem +13 -0
  271. data/remind-v06.02.10/include/holidays/it/ba.rem +13 -0
  272. data/remind-v06.02.10/include/holidays/it/barletta.rem +13 -0
  273. data/remind-v06.02.10/include/holidays/it/bg.rem +13 -0
  274. data/remind-v06.02.10/include/holidays/it/bl.rem +13 -0
  275. data/remind-v06.02.10/include/holidays/it/bn.rem +13 -0
  276. data/remind-v06.02.10/include/holidays/it/bo.rem +13 -0
  277. data/remind-v06.02.10/include/holidays/it/br.rem +13 -0
  278. data/remind-v06.02.10/include/holidays/it/bs.rem +13 -0
  279. data/remind-v06.02.10/include/holidays/it/bt.rem +15 -0
  280. data/remind-v06.02.10/include/holidays/it/bz.rem +14 -0
  281. data/remind-v06.02.10/include/holidays/it/ca.rem +13 -0
  282. data/remind-v06.02.10/include/holidays/it/cb.rem +13 -0
  283. data/remind-v06.02.10/include/holidays/it/ce.rem +13 -0
  284. data/remind-v06.02.10/include/holidays/it/cesena.rem +13 -0
  285. data/remind-v06.02.10/include/holidays/it/ch.rem +13 -0
  286. data/remind-v06.02.10/include/holidays/it/cl.rem +13 -0
  287. data/remind-v06.02.10/include/holidays/it/cn.rem +13 -0
  288. data/remind-v06.02.10/include/holidays/it/co.rem +13 -0
  289. data/remind-v06.02.10/include/holidays/it/cr.rem +13 -0
  290. data/remind-v06.02.10/include/holidays/it/cs.rem +13 -0
  291. data/remind-v06.02.10/include/holidays/it/ct.rem +13 -0
  292. data/remind-v06.02.10/include/holidays/it/cz.rem +13 -0
  293. data/remind-v06.02.10/include/holidays/it/en.rem +13 -0
  294. data/remind-v06.02.10/include/holidays/it/fc.rem +14 -0
  295. data/remind-v06.02.10/include/holidays/it/fe.rem +13 -0
  296. data/remind-v06.02.10/include/holidays/it/fg.rem +13 -0
  297. data/remind-v06.02.10/include/holidays/it/fi.rem +13 -0
  298. data/remind-v06.02.10/include/holidays/it/fm.rem +14 -0
  299. data/remind-v06.02.10/include/holidays/it/forli.rem +13 -0
  300. data/remind-v06.02.10/include/holidays/it/fr.rem +13 -0
  301. data/remind-v06.02.10/include/holidays/it/ge.rem +13 -0
  302. data/remind-v06.02.10/include/holidays/it/go.rem +13 -0
  303. data/remind-v06.02.10/include/holidays/it/gr.rem +13 -0
  304. data/remind-v06.02.10/include/holidays/it/im.rem +13 -0
  305. data/remind-v06.02.10/include/holidays/it/is.rem +13 -0
  306. data/remind-v06.02.10/include/holidays/it/kr.rem +13 -0
  307. data/remind-v06.02.10/include/holidays/it/lc.rem +13 -0
  308. data/remind-v06.02.10/include/holidays/it/le.rem +13 -0
  309. data/remind-v06.02.10/include/holidays/it/li.rem +13 -0
  310. data/remind-v06.02.10/include/holidays/it/lo.rem +13 -0
  311. data/remind-v06.02.10/include/holidays/it/lt.rem +14 -0
  312. data/remind-v06.02.10/include/holidays/it/lu.rem +13 -0
  313. data/remind-v06.02.10/include/holidays/it/mb.rem +13 -0
  314. data/remind-v06.02.10/include/holidays/it/mc.rem +13 -0
  315. data/remind-v06.02.10/include/holidays/it/me.rem +13 -0
  316. data/remind-v06.02.10/include/holidays/it/mi.rem +13 -0
  317. data/remind-v06.02.10/include/holidays/it/mn.rem +13 -0
  318. data/remind-v06.02.10/include/holidays/it/mo.rem +13 -0
  319. data/remind-v06.02.10/include/holidays/it/ms.rem +13 -0
  320. data/remind-v06.02.10/include/holidays/it/mt.rem +13 -0
  321. data/remind-v06.02.10/include/holidays/it/na.rem +13 -0
  322. data/remind-v06.02.10/include/holidays/it/no.rem +13 -0
  323. data/remind-v06.02.10/include/holidays/it/nu.rem +13 -0
  324. data/remind-v06.02.10/include/holidays/it/or.rem +13 -0
  325. data/remind-v06.02.10/include/holidays/it/pa.rem +13 -0
  326. data/remind-v06.02.10/include/holidays/it/pc.rem +13 -0
  327. data/remind-v06.02.10/include/holidays/it/pd.rem +13 -0
  328. data/remind-v06.02.10/include/holidays/it/pe.rem +13 -0
  329. data/remind-v06.02.10/include/holidays/it/pesaro.rem +13 -0
  330. data/remind-v06.02.10/include/holidays/it/pg.rem +14 -0
  331. data/remind-v06.02.10/include/holidays/it/pi.rem +13 -0
  332. data/remind-v06.02.10/include/holidays/it/pn.rem +14 -0
  333. data/remind-v06.02.10/include/holidays/it/pr.rem +13 -0
  334. data/remind-v06.02.10/include/holidays/it/pt.rem +13 -0
  335. data/remind-v06.02.10/include/holidays/it/pu.rem +14 -0
  336. data/remind-v06.02.10/include/holidays/it/pv.rem +13 -0
  337. data/remind-v06.02.10/include/holidays/it/pz.rem +13 -0
  338. data/remind-v06.02.10/include/holidays/it/ra.rem +13 -0
  339. data/remind-v06.02.10/include/holidays/it/rc.rem +13 -0
  340. data/remind-v06.02.10/include/holidays/it/re.rem +13 -0
  341. data/remind-v06.02.10/include/holidays/it/rg.rem +14 -0
  342. data/remind-v06.02.10/include/holidays/it/ri.rem +13 -0
  343. data/remind-v06.02.10/include/holidays/it/rm.rem +13 -0
  344. data/remind-v06.02.10/include/holidays/it/rn.rem +13 -0
  345. data/remind-v06.02.10/include/holidays/it/ro.rem +13 -0
  346. data/remind-v06.02.10/include/holidays/it/sa.rem +13 -0
  347. data/remind-v06.02.10/include/holidays/it/si.rem +13 -0
  348. data/remind-v06.02.10/include/holidays/it/so.rem +13 -0
  349. data/remind-v06.02.10/include/holidays/it/sp.rem +13 -0
  350. data/remind-v06.02.10/include/holidays/it/sr.rem +13 -0
  351. data/remind-v06.02.10/include/holidays/it/ss.rem +13 -0
  352. data/remind-v06.02.10/include/holidays/it/su.rem +13 -0
  353. data/remind-v06.02.10/include/holidays/it/sv.rem +13 -0
  354. data/remind-v06.02.10/include/holidays/it/ta.rem +13 -0
  355. data/remind-v06.02.10/include/holidays/it/te.rem +13 -0
  356. data/remind-v06.02.10/include/holidays/it/tn.rem +13 -0
  357. data/remind-v06.02.10/include/holidays/it/to.rem +13 -0
  358. data/remind-v06.02.10/include/holidays/it/tp.rem +13 -0
  359. data/remind-v06.02.10/include/holidays/it/tr.rem +13 -0
  360. data/remind-v06.02.10/include/holidays/it/trani.rem +13 -0
  361. data/remind-v06.02.10/include/holidays/it/ts.rem +13 -0
  362. data/remind-v06.02.10/include/holidays/it/tv.rem +13 -0
  363. data/remind-v06.02.10/include/holidays/it/ud.rem +13 -0
  364. data/remind-v06.02.10/include/holidays/it/urbino.rem +13 -0
  365. data/remind-v06.02.10/include/holidays/it/va.rem +13 -0
  366. data/remind-v06.02.10/include/holidays/it/vb.rem +13 -0
  367. data/remind-v06.02.10/include/holidays/it/vc.rem +13 -0
  368. data/remind-v06.02.10/include/holidays/it/ve.rem +14 -0
  369. data/remind-v06.02.10/include/holidays/it/vi.rem +13 -0
  370. data/remind-v06.02.10/include/holidays/it/vr.rem +13 -0
  371. data/remind-v06.02.10/include/holidays/it/vt.rem +13 -0
  372. data/remind-v06.02.10/include/holidays/it/vv.rem +13 -0
  373. data/remind-v06.02.10/include/holidays/it.rem +26 -0
  374. data/remind-v06.02.10/include/holidays/je.rem +19 -0
  375. data/remind-v06.02.10/include/holidays/jewish.rem +135 -0
  376. data/remind-v06.02.10/include/holidays/jm.rem +24 -0
  377. data/remind-v06.02.10/include/holidays/jo.rem +11 -0
  378. data/remind-v06.02.10/include/holidays/jp.rem +27 -0
  379. data/remind-v06.02.10/include/holidays/ke.rem +25 -0
  380. data/remind-v06.02.10/include/holidays/kg.rem +20 -0
  381. data/remind-v06.02.10/include/holidays/kh.rem +22 -0
  382. data/remind-v06.02.10/include/holidays/kn.rem +28 -0
  383. data/remind-v06.02.10/include/holidays/kr.rem +19 -0
  384. data/remind-v06.02.10/include/holidays/kw.rem +10 -0
  385. data/remind-v06.02.10/include/holidays/kz.rem +34 -0
  386. data/remind-v06.02.10/include/holidays/la.rem +47 -0
  387. data/remind-v06.02.10/include/holidays/lgbtq/au.rem +8 -0
  388. data/remind-v06.02.10/include/holidays/lgbtq/br.rem +10 -0
  389. data/remind-v06.02.10/include/holidays/lgbtq/ca.rem +7 -0
  390. data/remind-v06.02.10/include/holidays/lgbtq/cl.rem +7 -0
  391. data/remind-v06.02.10/include/holidays/lgbtq/ie.rem +7 -0
  392. data/remind-v06.02.10/include/holidays/lgbtq/in.rem +7 -0
  393. data/remind-v06.02.10/include/holidays/lgbtq/nl.rem +7 -0
  394. data/remind-v06.02.10/include/holidays/lgbtq/ua.rem +7 -0
  395. data/remind-v06.02.10/include/holidays/lgbtq/uk.rem +8 -0
  396. data/remind-v06.02.10/include/holidays/lgbtq/us.rem +16 -0
  397. data/remind-v06.02.10/include/holidays/lgbtq.rem +34 -0
  398. data/remind-v06.02.10/include/holidays/li.rem +31 -0
  399. data/remind-v06.02.10/include/holidays/ls.rem +18 -0
  400. data/remind-v06.02.10/include/holidays/lt.rem +23 -0
  401. data/remind-v06.02.10/include/holidays/lu.rem +18 -0
  402. data/remind-v06.02.10/include/holidays/lv.rem +25 -0
  403. data/remind-v06.02.10/include/holidays/ma.rem +17 -0
  404. data/remind-v06.02.10/include/holidays/mc.rem +26 -0
  405. data/remind-v06.02.10/include/holidays/md.rem +21 -0
  406. data/remind-v06.02.10/include/holidays/me.rem +28 -0
  407. data/remind-v06.02.10/include/holidays/mg.rem +24 -0
  408. data/remind-v06.02.10/include/holidays/mh.rem +22 -0
  409. data/remind-v06.02.10/include/holidays/misc.rem +9 -0
  410. data/remind-v06.02.10/include/holidays/mk.rem +17 -0
  411. data/remind-v06.02.10/include/holidays/mp.rem +44 -0
  412. data/remind-v06.02.10/include/holidays/mr.rem +11 -0
  413. data/remind-v06.02.10/include/holidays/mt.rem +21 -0
  414. data/remind-v06.02.10/include/holidays/mv.rem +12 -0
  415. data/remind-v06.02.10/include/holidays/mw.rem +36 -0
  416. data/remind-v06.02.10/include/holidays/mx.rem +15 -0
  417. data/remind-v06.02.10/include/holidays/my/01.rem +13 -0
  418. data/remind-v06.02.10/include/holidays/my/02.rem +13 -0
  419. data/remind-v06.02.10/include/holidays/my/03.rem +14 -0
  420. data/remind-v06.02.10/include/holidays/my/04.rem +18 -0
  421. data/remind-v06.02.10/include/holidays/my/05.rem +16 -0
  422. data/remind-v06.02.10/include/holidays/my/06.rem +17 -0
  423. data/remind-v06.02.10/include/holidays/my/07.rem +17 -0
  424. data/remind-v06.02.10/include/holidays/my/08.rem +15 -0
  425. data/remind-v06.02.10/include/holidays/my/09.rem +14 -0
  426. data/remind-v06.02.10/include/holidays/my/10.rem +16 -0
  427. data/remind-v06.02.10/include/holidays/my/11.rem +16 -0
  428. data/remind-v06.02.10/include/holidays/my/12.rem +19 -0
  429. data/remind-v06.02.10/include/holidays/my/13.rem +22 -0
  430. data/remind-v06.02.10/include/holidays/my/14.rem +16 -0
  431. data/remind-v06.02.10/include/holidays/my/15.rem +18 -0
  432. data/remind-v06.02.10/include/holidays/my/16.rem +16 -0
  433. data/remind-v06.02.10/include/holidays/my.rem +23 -0
  434. data/remind-v06.02.10/include/holidays/mz.rem +25 -0
  435. data/remind-v06.02.10/include/holidays/na.rem +27 -0
  436. data/remind-v06.02.10/include/holidays/ng.rem +21 -0
  437. data/remind-v06.02.10/include/holidays/ni/mn.rem +14 -0
  438. data/remind-v06.02.10/include/holidays/ni.rem +24 -0
  439. data/remind-v06.02.10/include/holidays/nl.rem +26 -0
  440. data/remind-v06.02.10/include/holidays/no.rem +19 -0
  441. data/remind-v06.02.10/include/holidays/nz/auk.rem +13 -0
  442. data/remind-v06.02.10/include/holidays/nz/can.rem +13 -0
  443. data/remind-v06.02.10/include/holidays/nz/cit.rem +13 -0
  444. data/remind-v06.02.10/include/holidays/nz/hkb.rem +13 -0
  445. data/remind-v06.02.10/include/holidays/nz/mbh.rem +13 -0
  446. data/remind-v06.02.10/include/holidays/nz/nsn.rem +13 -0
  447. data/remind-v06.02.10/include/holidays/nz/ntl.rem +13 -0
  448. data/remind-v06.02.10/include/holidays/nz/ota.rem +14 -0
  449. data/remind-v06.02.10/include/holidays/nz/south_canterbury.rem +13 -0
  450. data/remind-v06.02.10/include/holidays/nz/stl.rem +13 -0
  451. data/remind-v06.02.10/include/holidays/nz/tki.rem +13 -0
  452. data/remind-v06.02.10/include/holidays/nz/wgn.rem +13 -0
  453. data/remind-v06.02.10/include/holidays/nz/wtc.rem +13 -0
  454. data/remind-v06.02.10/include/holidays/nz.rem +69 -0
  455. data/remind-v06.02.10/include/holidays/pa.rem +27 -0
  456. data/remind-v06.02.10/include/holidays/pagan.rem +65 -0
  457. data/remind-v06.02.10/include/holidays/pe.rem +22 -0
  458. data/remind-v06.02.10/include/holidays/pg.rem +24 -0
  459. data/remind-v06.02.10/include/holidays/ph.rem +26 -0
  460. data/remind-v06.02.10/include/holidays/pk.rem +13 -0
  461. data/remind-v06.02.10/include/holidays/pl.rem +20 -0
  462. data/remind-v06.02.10/include/holidays/pr.rem +40 -0
  463. data/remind-v06.02.10/include/holidays/pt/01.rem +13 -0
  464. data/remind-v06.02.10/include/holidays/pt/02.rem +13 -0
  465. data/remind-v06.02.10/include/holidays/pt/03.rem +13 -0
  466. data/remind-v06.02.10/include/holidays/pt/04.rem +13 -0
  467. data/remind-v06.02.10/include/holidays/pt/05.rem +13 -0
  468. data/remind-v06.02.10/include/holidays/pt/06.rem +13 -0
  469. data/remind-v06.02.10/include/holidays/pt/07.rem +13 -0
  470. data/remind-v06.02.10/include/holidays/pt/08.rem +13 -0
  471. data/remind-v06.02.10/include/holidays/pt/09.rem +13 -0
  472. data/remind-v06.02.10/include/holidays/pt/10.rem +13 -0
  473. data/remind-v06.02.10/include/holidays/pt/12.rem +13 -0
  474. data/remind-v06.02.10/include/holidays/pt/13.rem +13 -0
  475. data/remind-v06.02.10/include/holidays/pt/14.rem +13 -0
  476. data/remind-v06.02.10/include/holidays/pt/15.rem +13 -0
  477. data/remind-v06.02.10/include/holidays/pt/16.rem +13 -0
  478. data/remind-v06.02.10/include/holidays/pt/18.rem +13 -0
  479. data/remind-v06.02.10/include/holidays/pt/20.rem +13 -0
  480. data/remind-v06.02.10/include/holidays/pt/30.rem +14 -0
  481. data/remind-v06.02.10/include/holidays/pt.rem +17 -0
  482. data/remind-v06.02.10/include/holidays/pw.rem +34 -0
  483. data/remind-v06.02.10/include/holidays/py.rem +20 -0
  484. data/remind-v06.02.10/include/holidays/ro.rem +24 -0
  485. data/remind-v06.02.10/include/holidays/rs.rem +26 -0
  486. data/remind-v06.02.10/include/holidays/ru.rem +21 -0
  487. data/remind-v06.02.10/include/holidays/sa.rem +13 -0
  488. data/remind-v06.02.10/include/holidays/sc.rem +28 -0
  489. data/remind-v06.02.10/include/holidays/se.rem +23 -0
  490. data/remind-v06.02.10/include/holidays/sg.rem +16 -0
  491. data/remind-v06.02.10/include/holidays/si.rem +20 -0
  492. data/remind-v06.02.10/include/holidays/sk.rem +25 -0
  493. data/remind-v06.02.10/include/holidays/sm.rem +25 -0
  494. data/remind-v06.02.10/include/holidays/sv/ss.rem +14 -0
  495. data/remind-v06.02.10/include/holidays/sv.rem +25 -0
  496. data/remind-v06.02.10/include/holidays/sz.rem +26 -0
  497. data/remind-v06.02.10/include/holidays/td.rem +22 -0
  498. data/remind-v06.02.10/include/holidays/th.rem +72 -0
  499. data/remind-v06.02.10/include/holidays/tl.rem +31 -0
  500. data/remind-v06.02.10/include/holidays/tn.rem +15 -0
  501. data/remind-v06.02.10/include/holidays/to.rem +38 -0
  502. data/remind-v06.02.10/include/holidays/tr.rem +17 -0
  503. data/remind-v06.02.10/include/holidays/tw.rem +26 -0
  504. data/remind-v06.02.10/include/holidays/tz.rem +23 -0
  505. data/remind-v06.02.10/include/holidays/ua.rem +20 -0
  506. data/remind-v06.02.10/include/holidays/uk.rem +27 -0
  507. data/remind-v06.02.10/include/holidays/um.rem +32 -0
  508. data/remind-v06.02.10/include/holidays/us/ak.rem +17 -0
  509. data/remind-v06.02.10/include/holidays/us/al.rem +17 -0
  510. data/remind-v06.02.10/include/holidays/us/ar.rem +13 -0
  511. data/remind-v06.02.10/include/holidays/us/as.rem +20 -0
  512. data/remind-v06.02.10/include/holidays/us/az.rem +14 -0
  513. data/remind-v06.02.10/include/holidays/us/ca.rem +16 -0
  514. data/remind-v06.02.10/include/holidays/us/co.rem +14 -0
  515. data/remind-v06.02.10/include/holidays/us/ct.rem +17 -0
  516. data/remind-v06.02.10/include/holidays/us/dc.rem +16 -0
  517. data/remind-v06.02.10/include/holidays/us/de.rem +14 -0
  518. data/remind-v06.02.10/include/holidays/us/fl.rem +14 -0
  519. data/remind-v06.02.10/include/holidays/us/ga.rem +18 -0
  520. data/remind-v06.02.10/include/holidays/us/gu.rem +17 -0
  521. data/remind-v06.02.10/include/holidays/us/hi.rem +19 -0
  522. data/remind-v06.02.10/include/holidays/us/ia.rem +15 -0
  523. data/remind-v06.02.10/include/holidays/us/id.rem +14 -0
  524. data/remind-v06.02.10/include/holidays/us/il.rem +17 -0
  525. data/remind-v06.02.10/include/holidays/us/in.rem +19 -0
  526. data/remind-v06.02.10/include/holidays/us/ks.rem +16 -0
  527. data/remind-v06.02.10/include/holidays/us/ky.rem +16 -0
  528. data/remind-v06.02.10/include/holidays/us/la.rem +14 -0
  529. data/remind-v06.02.10/include/holidays/us/ma.rem +17 -0
  530. data/remind-v06.02.10/include/holidays/us/md-extra.rem +19 -0
  531. data/remind-v06.02.10/include/holidays/us/md.rem +14 -0
  532. data/remind-v06.02.10/include/holidays/us/me.rem +14 -0
  533. data/remind-v06.02.10/include/holidays/us/mi.rem +19 -0
  534. data/remind-v06.02.10/include/holidays/us/mo.rem +16 -0
  535. data/remind-v06.02.10/include/holidays/us/mp.rem +23 -0
  536. data/remind-v06.02.10/include/holidays/us/ms.rem +14 -0
  537. data/remind-v06.02.10/include/holidays/us/mt.rem +13 -0
  538. data/remind-v06.02.10/include/holidays/us/nc.rem +22 -0
  539. data/remind-v06.02.10/include/holidays/us/ne.rem +14 -0
  540. data/remind-v06.02.10/include/holidays/us/nh.rem +14 -0
  541. data/remind-v06.02.10/include/holidays/us/nj.rem +17 -0
  542. data/remind-v06.02.10/include/holidays/us/nm.rem +14 -0
  543. data/remind-v06.02.10/include/holidays/us/nv.rem +16 -0
  544. data/remind-v06.02.10/include/holidays/us/ny.rem +17 -0
  545. data/remind-v06.02.10/include/holidays/us/oh.rem +13 -0
  546. data/remind-v06.02.10/include/holidays/us/ok.rem +13 -0
  547. data/remind-v06.02.10/include/holidays/us/pa.rem +14 -0
  548. data/remind-v06.02.10/include/holidays/us/pr.rem +21 -0
  549. data/remind-v06.02.10/include/holidays/us/ri.rem +14 -0
  550. data/remind-v06.02.10/include/holidays/us/sc.rem +13 -0
  551. data/remind-v06.02.10/include/holidays/us/sd.rem +13 -0
  552. data/remind-v06.02.10/include/holidays/us/tn.rem +13 -0
  553. data/remind-v06.02.10/include/holidays/us/tx.rem +25 -0
  554. data/remind-v06.02.10/include/holidays/us/ut.rem +16 -0
  555. data/remind-v06.02.10/include/holidays/us/va.rem +13 -0
  556. data/remind-v06.02.10/include/holidays/us/vi.rem +22 -0
  557. data/remind-v06.02.10/include/holidays/us/vt.rem +16 -0
  558. data/remind-v06.02.10/include/holidays/us/wi.rem +20 -0
  559. data/remind-v06.02.10/include/holidays/us/wv.rem +17 -0
  560. data/remind-v06.02.10/include/holidays/us.rem +41 -0
  561. data/remind-v06.02.10/include/holidays/uy.rem +39 -0
  562. data/remind-v06.02.10/include/holidays/uz.rem +21 -0
  563. data/remind-v06.02.10/include/holidays/va.rem +23 -0
  564. data/remind-v06.02.10/include/holidays/ve.rem +21 -0
  565. data/remind-v06.02.10/include/holidays/vi.rem +41 -0
  566. data/remind-v06.02.10/include/holidays/vn.rem +17 -0
  567. data/remind-v06.02.10/include/holidays/vu.rem +32 -0
  568. data/remind-v06.02.10/include/holidays/ws.rem +18 -0
  569. data/remind-v06.02.10/include/holidays/za.rem +28 -0
  570. data/remind-v06.02.10/include/holidays/zm.rem +31 -0
  571. data/remind-v06.02.10/include/lang/auto.rem +32 -0
  572. data/remind-v06.02.10/include/lang/ca.rem +60 -0
  573. data/remind-v06.02.10/include/lang/da.rem +77 -0
  574. data/remind-v06.02.10/include/lang/de.rem +80 -0
  575. data/remind-v06.02.10/include/lang/en.rem +4 -0
  576. data/remind-v06.02.10/include/lang/es.rem +55 -0
  577. data/remind-v06.02.10/include/lang/fi.rem +202 -0
  578. data/remind-v06.02.10/include/lang/fr.rem +172 -0
  579. data/remind-v06.02.10/include/lang/gr.rem +74 -0
  580. data/remind-v06.02.10/include/lang/is.rem +58 -0
  581. data/remind-v06.02.10/include/lang/it.rem +76 -0
  582. data/remind-v06.02.10/include/lang/nl.rem +71 -0
  583. data/remind-v06.02.10/include/lang/no.rem +66 -0
  584. data/remind-v06.02.10/include/lang/pl.rem +177 -0
  585. data/remind-v06.02.10/include/lang/pt.rem +176 -0
  586. data/remind-v06.02.10/include/lang/ro.rem +74 -0
  587. data/remind-v06.02.10/include/lunar-eclipses.rem +149 -0
  588. data/remind-v06.02.10/include/moonphases.rem +19 -0
  589. data/remind-v06.02.10/include/seasons.rem +21 -0
  590. data/remind-v06.02.10/include/solar-eclipses.rem +238 -0
  591. data/remind-v06.02.10/include/sun.rem +12 -0
  592. data/remind-v06.02.10/include/translations/de/holidays/chinese-new-year.rem +13 -0
  593. data/remind-v06.02.10/include/translations/de/moonphases.rem +4 -0
  594. data/remind-v06.02.10/include/translations/de/seasons.rem +4 -0
  595. data/remind-v06.02.10/include/translations/de/sun.rem +2 -0
  596. data/remind-v06.02.10/include/translations/nl/holidays/chinese-new-year.rem +13 -0
  597. data/remind-v06.02.10/include/translations/nl/moonphases.rem +4 -0
  598. data/remind-v06.02.10/include/translations/nl/seasons.rem +4 -0
  599. data/remind-v06.02.10/include/translations/nl/sun.rem +2 -0
  600. data/remind-v06.02.10/include/utils/add-html-anchors.rem +5 -0
  601. data/remind-v06.02.10/install-sh +238 -0
  602. data/remind-v06.02.10/man/rem.1.in +21 -0
  603. data/remind-v06.02.10/man/rem2ps.1.in +816 -0
  604. data/remind-v06.02.10/man/remind.1.in +7658 -0
  605. data/remind-v06.02.10/man/tkremind.1.in +612 -0
  606. data/remind-v06.02.10/rem2html/Makefile.in +30 -0
  607. data/remind-v06.02.10/rem2html/rem2html.in +1299 -0
  608. data/remind-v06.02.10/rem2pdf/Makefile.PL.in +25 -0
  609. data/remind-v06.02.10/rem2pdf/Makefile.top.in +50 -0
  610. data/remind-v06.02.10/rem2pdf/bin/rem2pdf.in +761 -0
  611. data/remind-v06.02.10/scripts/tkremind.in +5794 -0
  612. data/remind-v06.02.10/src/Makefile.in +133 -0
  613. data/remind-v06.02.10/src/calendar.c +3069 -0
  614. data/remind-v06.02.10/src/config.h +117 -0
  615. data/remind-v06.02.10/src/config.h.in +116 -0
  616. data/remind-v06.02.10/src/custom.h +167 -0
  617. data/remind-v06.02.10/src/custom.h.in +167 -0
  618. data/remind-v06.02.10/src/dedupe.c +179 -0
  619. data/remind-v06.02.10/src/dorem.c +2389 -0
  620. data/remind-v06.02.10/src/dosubst.c +910 -0
  621. data/remind-v06.02.10/src/dynbuf.c +198 -0
  622. data/remind-v06.02.10/src/dynbuf.h +41 -0
  623. data/remind-v06.02.10/src/err.h +294 -0
  624. data/remind-v06.02.10/src/expr.c +3408 -0
  625. data/remind-v06.02.10/src/files.c +1437 -0
  626. data/remind-v06.02.10/src/funcs.c +5230 -0
  627. data/remind-v06.02.10/src/globals.c +23 -0
  628. data/remind-v06.02.10/src/globals.h +277 -0
  629. data/remind-v06.02.10/src/hashtab.c +428 -0
  630. data/remind-v06.02.10/src/hashtab.h +88 -0
  631. data/remind-v06.02.10/src/hashtab_stats.c +101 -0
  632. data/remind-v06.02.10/src/hbcal.c +579 -0
  633. data/remind-v06.02.10/src/ifelse.c +236 -0
  634. data/remind-v06.02.10/src/init.c +1494 -0
  635. data/remind-v06.02.10/src/json.c +1048 -0
  636. data/remind-v06.02.10/src/json.h +276 -0
  637. data/remind-v06.02.10/src/main.c +2310 -0
  638. data/remind-v06.02.10/src/md5.c +250 -0
  639. data/remind-v06.02.10/src/md5.h +33 -0
  640. data/remind-v06.02.10/src/moon.c +957 -0
  641. data/remind-v06.02.10/src/omit.c +560 -0
  642. data/remind-v06.02.10/src/protos.h +284 -0
  643. data/remind-v06.02.10/src/queue.c +1118 -0
  644. data/remind-v06.02.10/src/rem2ps.c +1383 -0
  645. data/remind-v06.02.10/src/rem2ps.h +229 -0
  646. data/remind-v06.02.10/src/sort.c +257 -0
  647. data/remind-v06.02.10/src/token.c +494 -0
  648. data/remind-v06.02.10/src/trans.c +544 -0
  649. data/remind-v06.02.10/src/trigger.c +871 -0
  650. data/remind-v06.02.10/src/types.h +341 -0
  651. data/remind-v06.02.10/src/userfns.c +810 -0
  652. data/remind-v06.02.10/src/utils.c +374 -0
  653. data/remind-v06.02.10/src/var.c +1762 -0
  654. data/remind-v06.02.10/src/version.h +1 -0
  655. data/remind-v06.02.10/src/version.h.in +1 -0
  656. data/remind-v06.02.10/src/xlat.c +100 -0
  657. data/remind-v06.02.10/www/Makefile.in +91 -0
  658. metadata +764 -0
@@ -0,0 +1,2310 @@
1
+ /***************************************************************/
2
+ /* */
3
+ /* MAIN.C */
4
+ /* */
5
+ /* Main program loop, as well as miscellaneous conversion */
6
+ /* routines, etc. */
7
+ /* */
8
+ /* This file is part of REMIND. */
9
+ /* Copyright (C) 1992-2026 by Dianne Skoll */
10
+ /* SPDX-License-Identifier: GPL-2.0-only */
11
+ /* */
12
+ /***************************************************************/
13
+
14
+ #define _XOPEN_SOURCE 600
15
+ #include "config.h"
16
+
17
+ #include <fcntl.h>
18
+ #include <sys/wait.h>
19
+ #include <errno.h>
20
+ #include <stdlib.h>
21
+ #include <unistd.h>
22
+ #include <stdio.h>
23
+ #include <signal.h>
24
+ #include <string.h>
25
+
26
+ #ifdef HAVE_STRINGS_H
27
+ #include <strings.h>
28
+ #endif
29
+
30
+ #include <stdarg.h>
31
+ #ifdef HAVE_LOCALE_H
32
+ #include <locale.h>
33
+ #endif
34
+
35
+ #include <ctype.h>
36
+ #if defined(HAVE_SYS_TIME_H)
37
+ #include <sys/time.h>
38
+ #endif
39
+ #include <time.h>
40
+
41
+ #include <sys/types.h>
42
+ #include <wctype.h>
43
+ #include <wchar.h>
44
+
45
+ #include "types.h"
46
+ #include "protos.h"
47
+ #include "globals.h"
48
+ #include "err.h"
49
+
50
+ static void DoReminders(void);
51
+ static int DoDebug(ParsePtr p);
52
+ static void ClearLastTriggers(void);
53
+ static int DoBanner(ParsePtr p);
54
+ static void SaveLastTimeTrig(TimeTrig const *t);
55
+
56
+ /* Macro for simplifying common block so as not to litter code */
57
+ #define OUTPUT(c) do { if (output) { DBufPutc(output, c); } else { putchar(c); } } while(0)
58
+
59
+ static void
60
+ exitfunc(void)
61
+ {
62
+ /* Kill any execution-time-limiter process */
63
+ unlimit_execution_time();
64
+
65
+ size_t num_mallocs, bytes_malloced;
66
+
67
+ if (DebugFlag & DB_UNUSED_VARS) {
68
+ DumpUnusedVars();
69
+ }
70
+ if (DebugFlag & DB_HASHSTATS) {
71
+ fflush(stdout);
72
+ fflush(ErrFp);
73
+ DBufGetMallocStats(&num_mallocs, &bytes_malloced);
74
+ fprintf(ErrFp, "DynBuf Mallocs: %lu mallocs; %lu bytes\n",
75
+ (unsigned long) num_mallocs, (unsigned long) bytes_malloced);
76
+ fprintf(ErrFp, "Variable hash table statistics:\n");
77
+ dump_var_hash_stats();
78
+
79
+ fprintf(ErrFp, "Function hash table statistics:\n");
80
+ dump_userfunc_hash_stats();
81
+
82
+ fprintf(ErrFp, "Dedupe hash table statistics:\n");
83
+ dump_dedupe_hash_stats();
84
+
85
+ fprintf(ErrFp, "Translation hash table statistics:\n");
86
+ dump_translation_hash_stats();
87
+
88
+ UnsetAllUserFuncs();
89
+ print_expr_nodes_stats();
90
+ if (MaxExprNodeFilename) {
91
+ fprintf(ErrFp, "Max expr node evaluations per line: %lu (%s:%d)\n", MaxExprNodesPerLine, MaxExprNodeFilename, MaxExprNodeLineNo);
92
+ } else {
93
+ fprintf(ErrFp, "Max expr node evaluations per line: %lu\n", MaxExprNodesPerLine);
94
+ }
95
+ fprintf(ErrFp, "Total expression node evaluations: %lu\n", ExpressionNodesEvaluated);
96
+ }
97
+ }
98
+
99
+ static void sigalrm(int sig)
100
+ {
101
+ UNUSED(sig);
102
+ if (ExpressionEvaluationTimeLimit) {
103
+ ExpressionTimeLimitExceeded = 1;
104
+ }
105
+ }
106
+
107
+ static void sigxcpu(int sig)
108
+ {
109
+
110
+ UNUSED(sig);
111
+ int r = write(STDERR_FILENO, "\n\nmax-execution-time exceeded.\n\n", 32);
112
+
113
+ /* Pretend to use r to avoid compiler warning */
114
+ /* cppcheck-suppress duplicateExpression */
115
+ /* cppcheck-suppress knownArgument */
116
+ _exit(1 + (r-r));
117
+ }
118
+
119
+ /***************************************************************/
120
+ /***************************************************************/
121
+ /** **/
122
+ /** Main Program Loop **/
123
+ /** **/
124
+ /***************************************************************/
125
+ /***************************************************************/
126
+ int main(int argc, char *argv[])
127
+ {
128
+ int pid;
129
+
130
+ struct sigaction act;
131
+
132
+ #ifdef HAVE_SETLOCALE
133
+ setlocale(LC_ALL, "");
134
+ #endif
135
+
136
+ /* The very first thing to do is to set up ErrFp to be stderr */
137
+ ErrFp = stderr;
138
+
139
+ /* Set up global vars */
140
+ ArgC = argc;
141
+ ArgV = (char const **) argv;
142
+
143
+ InitRemind(argc, (char const **) argv);
144
+
145
+ act.sa_handler = sigalrm;
146
+ sigemptyset(&act.sa_mask);
147
+ act.sa_flags = SA_RESTART;
148
+ if (sigaction(SIGALRM, &act, NULL) < 0) {
149
+ fprintf(ErrFp, "%s: sigaction() failed: %s\n",
150
+ argv[0], strerror(errno));
151
+ exit(1);
152
+ }
153
+
154
+ act.sa_handler = sigxcpu;
155
+ act.sa_flags = SA_RESTART;
156
+ sigemptyset(&act.sa_mask);
157
+ if (sigaction(SIGXCPU, &act, NULL) < 0) {
158
+ fprintf(ErrFp, "%s: sigaction() failed: %s\n",
159
+ argv[0], strerror(errno));
160
+ exit(1);
161
+ }
162
+
163
+ DBufInit(&(LastTrigger.tags));
164
+ LastTrigger.infos = NULL;
165
+ LastTrigger.tz = NULL;
166
+ ClearLastTriggers();
167
+
168
+ atexit(exitfunc);
169
+
170
+ if (IsCalendarMode()) {
171
+ ProduceCalendar();
172
+ return 0;
173
+ }
174
+
175
+ /* Are we purging old reminders? Then just run through the loop once! */
176
+ if (PurgeMode) {
177
+ DoReminders();
178
+ return 0;
179
+ }
180
+
181
+ /* Not doing a calendar. Do the regular remind loop */
182
+ ShouldCache = (Iterations > 1);
183
+
184
+ while (Iterations--) {
185
+ if (JSONMode) {
186
+ printf("[\n");
187
+ }
188
+ PerIterationInit();
189
+ DoReminders();
190
+
191
+ if (DebugFlag & DB_DUMP_VARS) {
192
+ DumpVarTable(0);
193
+ DumpSysVarByName(NULL);
194
+ }
195
+
196
+ if (!Hush) {
197
+ if (DestroyOmitContexts(1)) {
198
+ FreshLine = 1;
199
+ Eprint("%s", GetErr(E_PUSH_NOPOP));
200
+ }
201
+ if (EmptyVarStack(1)) {
202
+ FreshLine = 1;
203
+ Eprint("%s", GetErr(E_PUSHV_NO_POP));
204
+ }
205
+ if (EmptyUserFuncStack(1)) {
206
+ FreshLine = 1;
207
+ Eprint("%s", GetErr(E_PUSHF_NO_POP));
208
+ }
209
+ if (!Daemon && !NextMode && !NumTriggered && !NumQueued) {
210
+ if (!JSONMode) {
211
+ printf("%s\n", GetErr(E_NOREMINDERS));
212
+ } else {
213
+ if (!DidMsgReminder) {
214
+ DynamicBuffer buf;
215
+ DBufInit(&buf);
216
+ /* Do a banner in JSON mode*/
217
+ if (!DoSubstFromString(DBufValue(&Banner), &buf,
218
+ DSEToday, NO_TIME) &&
219
+ DBufLen(&buf)) {
220
+ if (JSONLinesEmitted) {
221
+ printf("},\n");
222
+ }
223
+ JSONLinesEmitted++;
224
+ printf("{\"banner\":\"");
225
+ remove_trailing_newlines(&buf);
226
+ PrintJSONString(DBufValue(&buf));
227
+ printf("\"");
228
+ }
229
+ DBufFree(&buf);
230
+ }
231
+ if (JSONLinesEmitted) {
232
+ printf("},\n");
233
+ }
234
+ printf("{\"noreminders\":\"");
235
+ PrintJSONString(GetErr(E_NOREMINDERS));
236
+ printf("\"");
237
+ JSONLinesEmitted++;
238
+ }
239
+ } else if (!Daemon && !NextMode && !NumTriggered) {
240
+ printf(GetErr(M_QUEUED), NumQueued);
241
+ printf("\n");
242
+ }
243
+ }
244
+
245
+ /* If there are sorted reminders, handle them */
246
+ if (SortByDate) IssueSortedReminders();
247
+
248
+ if (JSONMode) {
249
+ if (JSONLinesEmitted) {
250
+ printf("}\n");
251
+ }
252
+ printf("]\n");
253
+ }
254
+ /* If there are any background reminders queued up, handle them */
255
+ if (NumQueued || Daemon) {
256
+
257
+ if (DontFork) {
258
+ HandleQueuedReminders();
259
+ return 0;
260
+ } else {
261
+ pid = fork();
262
+ if (pid == 0) {
263
+ HandleQueuedReminders();
264
+ return 0;
265
+ }
266
+ if (pid == -1) {
267
+ fprintf(ErrFp, "%s", GetErr(E_CANTFORK));
268
+ return 1;
269
+ }
270
+ }
271
+ }
272
+ if (Iterations) {
273
+ DSEToday++;
274
+ }
275
+ }
276
+ return 0;
277
+ }
278
+
279
+ void PurgeEchoLine(char const *fmt, ...)
280
+ {
281
+ va_list argptr;
282
+ va_start(argptr, fmt);
283
+ if (PurgeFP != NULL) {
284
+ (void) vfprintf(PurgeFP, fmt, argptr);
285
+ }
286
+ va_end(argptr);
287
+
288
+ }
289
+
290
+ void
291
+ PerIterationInit(void)
292
+ {
293
+ ClearGlobalOmits();
294
+ DestroyOmitContexts(1);
295
+ EmptyVarStack(1);
296
+ EmptyUserFuncStack(1);
297
+ DestroyVars(0);
298
+ DefaultColorR = -1;
299
+ DefaultColorG = -1;
300
+ DefaultColorB = -1;
301
+ NumTriggered = 0;
302
+ Shaded = 0;
303
+ JSONLinesEmitted = 0;
304
+ ClearLastTriggers();
305
+ ClearDedupeTable();
306
+ }
307
+
308
+ /***************************************************************/
309
+ /* */
310
+ /* DoReminders */
311
+ /* */
312
+ /* The normal case - we're not doing a calendar. */
313
+ /* */
314
+ /***************************************************************/
315
+ static void DoReminders(void)
316
+ {
317
+ int r;
318
+ Token tok;
319
+ char const *s;
320
+ Parser p;
321
+ int purge_handled;
322
+
323
+ DidMsgReminder = 0;
324
+
325
+ if (!UseStdin) {
326
+ FileAccessDate = GetAccessDate(InitialFile);
327
+ } else {
328
+ FileAccessDate = DSEToday - 1;
329
+ if (FileAccessDate < 0) FileAccessDate = 0;
330
+ }
331
+
332
+ if (FileAccessDate < 0) {
333
+ fprintf(ErrFp, "%s: `%s': %s.\n", GetErr(E_CANTOPEN), InitialFile, strerror(errno));
334
+ exit(EXIT_FAILURE);
335
+ }
336
+
337
+ r=IncludeFile(InitialFile);
338
+ if (r) {
339
+ fprintf(ErrFp, "%s %s: %s\n", GetErr(E_ERR_READING),
340
+ InitialFile, GetErr(r));
341
+ exit(EXIT_FAILURE);
342
+ }
343
+
344
+ while(1) {
345
+ r = ReadLine();
346
+ if (r == E_EOF) return;
347
+ if (r) {
348
+ Eprint("%s: %s", GetErr(E_ERR_READING), GetErr(r));
349
+ exit(EXIT_FAILURE);
350
+ }
351
+ s = FindInitialToken(&tok, CurLine);
352
+
353
+ /* Should we ignore it? */
354
+ if (tok.type != T_If &&
355
+ tok.type != T_Else &&
356
+ tok.type != T_EndIf &&
357
+ tok.type != T_IfTrig &&
358
+ tok.type != T_Set &&
359
+ tok.type != T_Fset &&
360
+ should_ignore_line())
361
+ {
362
+ /*** IGNORE THE LINE ***/
363
+ if (PurgeMode) {
364
+ if (strncmp(CurLine, "#!P", 3)) {
365
+ PurgeEchoLine("%s\n", CurLine);
366
+ }
367
+ }
368
+ }
369
+ else {
370
+ purge_handled = 0;
371
+ /* Create a parser to parse the line */
372
+ CreateParser(s, &p);
373
+ switch(tok.type) {
374
+
375
+ case T_Empty:
376
+ case T_Comment:
377
+ if (!strncmp(CurLine, "#!P", 3)) {
378
+ purge_handled = 1;
379
+ }
380
+ break;
381
+
382
+ case T_Rem: r=DoRem(&p); purge_handled = 1; break;
383
+ case T_ErrMsg: r=DoErrMsg(&p); break;
384
+ case T_If: r=DoIf(&p); break;
385
+ case T_Return: r=DoReturn(&p); break;
386
+ case T_IfTrig: r=DoIfTrig(&p); break;
387
+ case T_Else: r=DoElse(&p); break;
388
+ case T_EndIf: r=DoEndif(&p); break;
389
+ case T_Include:
390
+ case T_IncludeR:
391
+ case T_IncludeSys:
392
+ /* In purge mode, include closes file, so we
393
+ need to echo it here! */
394
+ if (PurgeMode) {
395
+ PurgeEchoLine("%s\n", CurLine);
396
+ }
397
+ r=DoInclude(&p, tok.type);
398
+ purge_handled = 1;
399
+ break;
400
+ case T_IncludeCmd:
401
+ /* In purge mode, include closes file, so we
402
+ need to echo it here! */
403
+ if (PurgeMode) {
404
+ PurgeEchoLine("%s\n", CurLine);
405
+ }
406
+ r=DoIncludeCmd(&p);
407
+ purge_handled = 1;
408
+ break;
409
+ case T_Exit: DoExit(&p); break;
410
+ case T_Flush: r=DoFlush(&p); break;
411
+ case T_Set: r=DoSet(&p); break;
412
+ case T_Fset: r=DoFset(&p); break;
413
+ case T_Funset: r=DoFunset(&p); break;
414
+ case T_Frename: r=DoFrename(&p); break;
415
+ case T_UnSet: r=DoUnset(&p); break;
416
+ case T_Clr: r=DoClear(&p); break;
417
+ case T_Debug: r=DoDebug(&p); break;
418
+ case T_Dumpvars: r=DoDump(&p); break;
419
+ case T_Banner: r=DoBanner(&p); break;
420
+ case T_Omit: r=DoOmit(&p);
421
+ if (r == E_PARSE_AS_REM) {
422
+ DestroyParser(&p);
423
+ CreateParser(s, &p);
424
+ r=DoRem(&p);
425
+ purge_handled = 1;
426
+ }
427
+ break;
428
+ case T_Pop: r=PopOmitContext(&p); break;
429
+ case T_Preserve: r=DoPreserve(&p); break;
430
+ case T_Push: r=PushOmitContext(&p); break;
431
+ case T_PushVars:
432
+ r=PushVars(&p);
433
+ break;
434
+ case T_PopVars:
435
+ r=PopVars(&p);
436
+ break;
437
+ case T_PushFuncs:
438
+ r=PushUserFuncs(&p);
439
+ break;
440
+ case T_PopFuncs:
441
+ r=PopUserFuncs(&p);
442
+ break;
443
+ case T_Expr: r = DoExpr(&p); break;
444
+ case T_Translate: r = DoTranslate(&p); break;
445
+ case T_RemType: if (tok.val == RUN_TYPE) {
446
+ r=DoRun(&p);
447
+ } else {
448
+ DestroyParser(&p);
449
+ CreateParser(CurLine, &p);
450
+ r=DoRem(&p);
451
+ purge_handled = 1;
452
+ }
453
+ break;
454
+
455
+
456
+ /* If we don't recognize the command, do a REM by default, but warn */
457
+
458
+ default:
459
+ if (!SuppressImplicitRemWarnings) {
460
+ if (warning_level("05.00.03")) {
461
+ Wprint(tr("Unrecognized command; interpreting as REM"));
462
+ }
463
+ WarnedAboutImplicit = 1;
464
+ }
465
+ DestroyParser(&p);
466
+ CreateParser(CurLine, &p);
467
+ purge_handled = 1;
468
+ r=DoRem(&p);
469
+ break;
470
+
471
+ }
472
+ if (r && (!Hush || r != E_RUN_DISABLED)) {
473
+ Eprint("%s", GetErr(r));
474
+ }
475
+ if (PurgeMode) {
476
+ if (!purge_handled) {
477
+ PurgeEchoLine("%s\n", CurLine);
478
+ } else {
479
+ if (r) {
480
+ if (!Hush) {
481
+ PurgeEchoLine("#!P! Could not parse next line: %s\n", GetErr(r));
482
+ }
483
+ PurgeEchoLine("%s\n", CurLine);
484
+ }
485
+ }
486
+ }
487
+ /* Destroy the parser - free up resources it may be tying up */
488
+ DestroyParser(&p);
489
+ }
490
+ }
491
+ }
492
+
493
+ /***************************************************************/
494
+ /* */
495
+ /* DSE */
496
+ /* */
497
+ /* DSE stands for "Days Since Epoch"; the Remind epoch is */
498
+ /* midnight on 1990-01-01 */
499
+ /* */
500
+ /* Given day, month, year, return DSE date in days since */
501
+ /* 1 January 1990. */
502
+ /* */
503
+ /***************************************************************/
504
+ int DSE(int year, int month, int day)
505
+ {
506
+ int y1 = BASE-1, y2 = year-1;
507
+
508
+ int y4 = (y2 / 4) - (y1 / 4); /* Correct for leap years */
509
+ int y100 = (y2 / 100) - (y1 / 100); /* Don't count multiples of 100... */
510
+ int y400 = (y2 / 400) - (y1 / 400); /* ... but do count multiples of 400 */
511
+
512
+ return 365 * (year-BASE) + y4 - y100 + y400 +
513
+ MonthIndex[IsLeapYear(year)][month] + day - 1;
514
+ }
515
+
516
+ /***************************************************************/
517
+ /* */
518
+ /* FromDSE */
519
+ /* */
520
+ /* Convert a DSE date to year, month, day. You may supply */
521
+ /* NULL for y, m or d if you're not interested in that value */
522
+ /* */
523
+ /***************************************************************/
524
+ void FromDSE(int dse, int *y, int *m, int *d)
525
+ {
526
+ int try_yr = (dse / 365) + BASE;
527
+ int try_mon = 0;
528
+ int t;
529
+
530
+ /* Inline code for speed... */
531
+ int y1 = BASE-1, y2 = try_yr-1;
532
+ int y4 = (y2 / 4) - (y1 / 4); /* Correct for leap years */
533
+ int y100 = (y2 / 100) - (y1 / 100); /* Don't count multiples of 100... */
534
+ int y400 = (y2 / 400) - (y1 / 400); /* ... but do count multiples of 400 */
535
+
536
+ int try_dse= 365 * (try_yr-BASE) + y4 - y100 + y400;
537
+
538
+ while (try_dse > dse) {
539
+ try_yr--;
540
+ try_dse -= DaysInYear(try_yr);
541
+ }
542
+ if (y) {
543
+ *y = try_yr;
544
+ }
545
+
546
+ /* If all we want is the year, we can quit here */
547
+ if (!d && !m) {
548
+ return;
549
+ }
550
+
551
+ dse -= try_dse;
552
+
553
+ t = DaysInMonth(try_mon, try_yr);
554
+ while (dse >= t) {
555
+ dse -= t;
556
+ try_mon++;
557
+ t = DaysInMonth(try_mon, try_yr);
558
+ }
559
+ if (m) {
560
+ *m = try_mon;
561
+ }
562
+ if (d) {
563
+ *d = dse + 1;
564
+ }
565
+ return;
566
+ }
567
+
568
+ int JulianToGregorianOffset(int y, int m)
569
+ {
570
+ int offset = 13;
571
+ int centuries;
572
+ int four_centuries;
573
+ if (y >= 2100) {
574
+ centuries = (y - 2000) / 100;
575
+ four_centuries = (y - 2000) / 400;
576
+ offset += centuries - four_centuries;
577
+ if (!(y%100) && (y % 400)) {
578
+ if (m < 2) {
579
+ offset--; /* Offset increments in March */
580
+ }
581
+ }
582
+ }
583
+ return offset;
584
+ }
585
+ /***************************************************************/
586
+ /* */
587
+ /* ParseChar */
588
+ /* */
589
+ /* Parse a character from a parse pointer. If peek is non- */
590
+ /* zero, then just peek ahead; don't advance pointer. */
591
+ /* */
592
+ /***************************************************************/
593
+ int ParseChar(ParsePtr p, int *err, int peek)
594
+ {
595
+ Value val;
596
+ int r;
597
+
598
+ *err = 0;
599
+ if (p->tokenPushed && *p->tokenPushed) {
600
+ if (peek) return *p->tokenPushed;
601
+ else {
602
+ r = *p->tokenPushed++;
603
+ if (!r) {
604
+ DBufFree(&p->pushedToken);
605
+ p->tokenPushed = NULL;
606
+ }
607
+ return r;
608
+ }
609
+ }
610
+
611
+ while(1) {
612
+ if (p->isnested) {
613
+ if (*(p->epos)) {
614
+ if (peek) {
615
+ return *(p->epos);
616
+ } else {
617
+ return *(p->epos++);
618
+ }
619
+ }
620
+ free((void *) p->etext); /* End of substituted expression */
621
+ p->etext = NULL;
622
+ p->epos = NULL;
623
+ p->isnested = 0;
624
+ }
625
+ if (!*(p->pos)) {
626
+ return 0;
627
+ }
628
+ if (*p->pos != BEG_OF_EXPR || !p->allownested) {
629
+ if (peek) {
630
+ return *(p->pos);
631
+ } else {
632
+ return *(p->pos++);
633
+ }
634
+ }
635
+
636
+ /* Convert [[ to just a literal [ */
637
+ if (*p->pos == BEG_OF_EXPR && *(p->pos+1) == BEG_OF_EXPR) {
638
+ if (peek) {
639
+ return *(p->pos+1);
640
+ } else {
641
+ p->pos++;
642
+ return *(p->pos++);
643
+ }
644
+ }
645
+ p->expr_happened = 1;
646
+ p->pos++;
647
+ r = EvalExpr(&(p->pos), &val, p);
648
+ if (r) {
649
+ *err = r;
650
+ DestroyParser(p);
651
+ return 0;
652
+ }
653
+ while(*p->pos && (isempty(*p->pos))) {
654
+ p->pos++;
655
+ }
656
+ if (*p->pos != END_OF_EXPR) {
657
+ if (*p->pos) {
658
+ *err = E_PARSE_ERR;
659
+ } else {
660
+ *err = E_MISS_END;
661
+ }
662
+ DestroyParser(p);
663
+ DestroyValue(val);
664
+ return 0;
665
+ }
666
+ p->pos++;
667
+ r = DoCoerce(STR_TYPE, &val);
668
+ if (r) { *err = r; return 0; }
669
+ p->etext = val.v.str;
670
+ val.type = ERR_TYPE; /* So it's not accidentally destroyed! */
671
+ p->isnested = 1;
672
+ p->epos = p->etext;
673
+ }
674
+ }
675
+
676
+ /***************************************************************/
677
+ /* */
678
+ /* ParseNonSpaceChar */
679
+ /* */
680
+ /* Parse the next non-space character. */
681
+ /* */
682
+ /***************************************************************/
683
+ int ParseNonSpaceChar(ParsePtr p, int *err, int peek)
684
+ {
685
+ int ch;
686
+
687
+ ch = ParseChar(p, err, 1);
688
+ if (*err) return 0;
689
+
690
+ while (isempty(ch)) {
691
+ ParseChar(p, err, 0); /* Guaranteed to work */
692
+ ch = ParseChar(p, err, 1);
693
+ if (*err) return 0;
694
+ }
695
+ if (!peek) ch = ParseChar(p, err, 0); /* Guaranteed to work */
696
+ return ch;
697
+ }
698
+
699
+ /***************************************************************/
700
+ /* */
701
+ /* ParseTokenOrQuotedString */
702
+ /* */
703
+ /* Parse either a token or a double-quote-delimited string. */
704
+ /* */
705
+ /***************************************************************/
706
+ int ParseTokenOrQuotedString(ParsePtr p, DynamicBuffer *dbuf)
707
+ {
708
+ int c, err;
709
+ c = ParseNonSpaceChar(p, &err, 1);
710
+ if (err) return err;
711
+ if (c != '"') {
712
+ return ParseToken(p, dbuf);
713
+ }
714
+ return ParseQuotedString(p, dbuf);
715
+ }
716
+
717
+ /***************************************************************/
718
+ /* */
719
+ /* ParseQuotedString */
720
+ /* */
721
+ /* Parse a double-quote-delimited string. */
722
+ /* */
723
+ /***************************************************************/
724
+ int ParseQuotedString(ParsePtr p, DynamicBuffer *dbuf)
725
+ {
726
+ int c, err, c2;
727
+ char hexbuf[3];
728
+
729
+ DBufFree(dbuf);
730
+ c = ParseNonSpaceChar(p, &err, 0);
731
+ if (err) return err;
732
+ if (!c) {
733
+ return E_EOLN;
734
+ }
735
+ if (c != '"') {
736
+ return E_MISS_QUOTE;
737
+ }
738
+ c = ParseChar(p, &err, 0);
739
+ if (err) {
740
+ DBufFree(dbuf);
741
+ return err;
742
+ }
743
+ while (c != 0 && c != '"') {
744
+ if (c == '\\') {
745
+ c = ParseChar(p, &err, 0);
746
+ if (err) {
747
+ DBufFree(dbuf);
748
+ return err;
749
+ }
750
+ switch(c) {
751
+ case 'a':
752
+ err = DBufPutc(dbuf, '\a');
753
+ break;
754
+ case 'b':
755
+ err = DBufPutc(dbuf, '\b');
756
+ break;
757
+ case 'f':
758
+ err = DBufPutc(dbuf, '\f');
759
+ break;
760
+ case 'n':
761
+ err = DBufPutc(dbuf, '\n');
762
+ break;
763
+ case 'r':
764
+ err = DBufPutc(dbuf, '\r');
765
+ break;
766
+ case 't':
767
+ err = DBufPutc(dbuf, '\t');
768
+ break;
769
+ case 'v':
770
+ err = DBufPutc(dbuf, '\v');
771
+ break;
772
+ case 'x':
773
+ /* \x Followed by one or two hex digits */
774
+ c2 = ParseChar(p, &err, 1);
775
+ if (err) break;
776
+ if (!isxdigit(c2)) {
777
+ err = DBufPutc(dbuf, c);
778
+ break;
779
+ }
780
+ hexbuf[0] = c2;
781
+ hexbuf[1] = 0;
782
+ c2 = ParseChar(p, &err, 0);
783
+ if (err) break;
784
+ c2 = ParseChar(p, &err, 1);
785
+ if (err) break;
786
+ if (isxdigit(c2)) {
787
+ hexbuf[1] = c2;
788
+ hexbuf[2] = 0;
789
+ c2 = ParseChar(p, &err, 0);
790
+ if (err) break;
791
+ }
792
+ c2 = (int) strtol(hexbuf, NULL, 16);
793
+ if (!c2) {
794
+ Eprint(tr("\\x00 is not a valid escape sequence"));
795
+ err = E_PARSE_ERR;
796
+ } else {
797
+ err = DBufPutc(dbuf, c2);
798
+ }
799
+ break;
800
+ default:
801
+ err = DBufPutc(dbuf, c);
802
+ }
803
+ } else {
804
+ err = DBufPutc(dbuf, c);
805
+ }
806
+ if (err) {
807
+ DBufFree(dbuf);
808
+ return err;
809
+ }
810
+ c = ParseChar(p, &err, 0);
811
+ if (err) {
812
+ DBufFree(dbuf);
813
+ return err;
814
+ }
815
+ }
816
+ if (c != '"') {
817
+ DBufFree(dbuf);
818
+ return E_MISS_QUOTE;
819
+ }
820
+ return OK;
821
+ }
822
+
823
+ /***************************************************************/
824
+ /* */
825
+ /* ParseToken */
826
+ /* */
827
+ /* Parse a token delimited by whitespace. */
828
+ /* */
829
+ /***************************************************************/
830
+ int ParseToken(ParsePtr p, DynamicBuffer *dbuf)
831
+ {
832
+ int c, err;
833
+
834
+ DBufFree(dbuf);
835
+
836
+ c = ParseChar(p, &err, 0);
837
+ if (err) return err;
838
+ while (c && isempty(c)) {
839
+ c = ParseChar(p, &err, 0);
840
+ if (err) return err;
841
+ }
842
+ if (!c) return OK;
843
+ while (c && !isempty(c)) {
844
+ if (DBufPutc(dbuf, c) != OK) {
845
+ DBufFree(dbuf);
846
+ return E_NO_MEM;
847
+ }
848
+ c = ParseChar(p, &err, 0);
849
+ if (err) {
850
+ DBufFree(dbuf);
851
+ return err;
852
+ }
853
+ }
854
+ return OK;
855
+ }
856
+
857
+ /***************************************************************/
858
+ /* */
859
+ /* ParseIdentifier */
860
+ /* */
861
+ /* Parse a valid identifier - ie, alpha or underscore */
862
+ /* followed by alphanum. Return E_BAD_ID if identifier is */
863
+ /* invalid. */
864
+ /* */
865
+ /***************************************************************/
866
+ int ParseIdentifier(ParsePtr p, DynamicBuffer *dbuf)
867
+ {
868
+ int c, err;
869
+
870
+ DBufFree(dbuf);
871
+
872
+ c = ParseChar(p, &err, 0);
873
+ if (err) return err;
874
+ while (c && isempty(c)) {
875
+ c = ParseChar(p, &err, 0);
876
+ if (err) return err;
877
+ }
878
+ if (!c) return E_EOLN;
879
+ if (c != '$' && c != '_' && !isalpha(c)) return E_BAD_ID;
880
+ if (DBufPutc(dbuf, c) != OK) {
881
+ DBufFree(dbuf);
882
+ return E_NO_MEM;
883
+ }
884
+
885
+ while (1) {
886
+ c = ParseChar(p, &err, 1);
887
+ if (err) {
888
+ DBufFree(dbuf);
889
+ return err;
890
+ }
891
+ if (c != '_' && !isalnum(c)) return OK;
892
+ c = ParseChar(p, &err, 0); /* Guaranteed to work */
893
+ if (DBufPutc(dbuf, c) != OK) {
894
+ DBufFree(dbuf);
895
+ return E_NO_MEM;
896
+ }
897
+ }
898
+ }
899
+
900
+ /***************************************************************/
901
+ /* */
902
+ /* ParseExpr */
903
+ /* */
904
+ /* We are expecting an expression here. Parse it and return */
905
+ /* the value node tree. */
906
+ /* */
907
+ /***************************************************************/
908
+ expr_node * ParseExpr(ParsePtr p, int *r)
909
+ {
910
+
911
+ int bracketed = 0;
912
+ expr_node *node;
913
+
914
+ if (p->isnested) {
915
+ *r = E_PARSE_ERR; /* Can't nest expressions */
916
+ return NULL;
917
+ }
918
+ if (!p->pos) {
919
+ *r = E_PARSE_ERR; /* Missing expression */
920
+ return NULL;
921
+ }
922
+
923
+ while (isempty(*p->pos)) (p->pos)++;
924
+ if (!*(p->pos)) {
925
+ *r = E_EOLN;
926
+ return NULL;
927
+ }
928
+ if (*p->pos == BEG_OF_EXPR) {
929
+ (p->pos)++;
930
+ bracketed = 1;
931
+ }
932
+ node = parse_expression(&(p->pos), r, NULL);
933
+ if (*r) {
934
+ return free_expr_tree(node);
935
+ }
936
+
937
+ if (bracketed) {
938
+ if (*p->pos != END_OF_EXPR) {
939
+ if (*p->pos) {
940
+ *r = E_PARSE_ERR;
941
+ } else {
942
+ *r = E_MISS_END;
943
+ }
944
+ return free_expr_tree(node);
945
+ }
946
+ (p->pos)++;
947
+ }
948
+ return node;
949
+ }
950
+
951
+ /***************************************************************/
952
+ /* */
953
+ /* EvaluateExpr */
954
+ /* */
955
+ /* We are expecting an expression here. Evaluate it and */
956
+ /* return the value. */
957
+ /* */
958
+ /***************************************************************/
959
+ int EvaluateExpr(ParsePtr p, Value *v)
960
+ {
961
+
962
+ int r;
963
+ int nonconst = 0;
964
+ expr_node *node = ParseExpr(p, &r);
965
+
966
+ if (r != OK) {
967
+ return r;
968
+ }
969
+ if (!node) {
970
+ return E_SWERR;
971
+ }
972
+
973
+ r = evaluate_expression(node, NULL, v, &nonconst);
974
+ free_expr_tree(node);
975
+ if (r) return r;
976
+ if (nonconst) {
977
+ p->nonconst_expr = 1;
978
+ }
979
+ return OK;
980
+ }
981
+
982
+ /***************************************************************/
983
+ /* */
984
+ /* Wprint - print a warning message. */
985
+ /* */
986
+ /***************************************************************/
987
+ void Wprint(char const *fmt, ...)
988
+ {
989
+ va_list argptr;
990
+
991
+ char const *fname = GetCurrentFilename();
992
+ if (SuppressErrorOutputInCatch) {
993
+ return;
994
+ }
995
+
996
+ /* We can't use line_range because caller might have used it */
997
+ if (fname) {
998
+ if (LineNoStart == LineNo) {
999
+ (void) fprintf(ErrFp, "%s(%d): ", fname, LineNo);
1000
+ } else {
1001
+ (void) fprintf(ErrFp, "%s(%d:%d): ", fname, LineNoStart, LineNo);
1002
+ }
1003
+ }
1004
+
1005
+ va_start(argptr, fmt);
1006
+ (void) vfprintf(ErrFp, fmt, argptr);
1007
+ (void) fputc('\n', ErrFp);
1008
+ va_end(argptr);
1009
+ return;
1010
+ }
1011
+ /***************************************************************/
1012
+ /* */
1013
+ /* Eprint - print an error message. */
1014
+ /* */
1015
+ /***************************************************************/
1016
+ void Eprint(char const *fmt, ...)
1017
+ {
1018
+ va_list argptr;
1019
+
1020
+ if (SuppressErrorOutputInCatch) {
1021
+ return;
1022
+ }
1023
+
1024
+ if (should_ignore_line()) {
1025
+ return;
1026
+ }
1027
+
1028
+ char const *fname = GetCurrentFilename();
1029
+ if (!fname) {
1030
+ return;
1031
+ }
1032
+
1033
+ if (LineNo < 1) {
1034
+ /* Not yet processing a file */
1035
+ return;
1036
+ }
1037
+ /* Check if more than one error msg. from this line */
1038
+ if (!FreshLine && !ShowAllErrors) return;
1039
+
1040
+ if (FreshLine) {
1041
+ /* We can't use line_range because caller might have used it */
1042
+ if (LineNo == LineNoStart) {
1043
+ (void) fprintf(ErrFp, "%s(%d): ", fname, LineNo);
1044
+ } else {
1045
+ (void) fprintf(ErrFp, "%s(%d:%d): ", fname, LineNoStart, LineNo);
1046
+ }
1047
+ } else {
1048
+ fprintf(ErrFp, " ");
1049
+ }
1050
+ va_start(argptr, fmt);
1051
+ (void) vfprintf(ErrFp, fmt, argptr);
1052
+ (void) fputc('\n', ErrFp);
1053
+ va_end(argptr);
1054
+ if (print_callstack(ErrFp)) {
1055
+ (void) fprintf(ErrFp, "\n");
1056
+ }
1057
+ if (FreshLine) {
1058
+ if (DebugFlag & DB_PRTLINE) OutputLine(ErrFp);
1059
+ }
1060
+ FreshLine = 0;
1061
+ }
1062
+
1063
+ /***************************************************************/
1064
+ /* */
1065
+ /* OutputLine */
1066
+ /* */
1067
+ /* Output a line from memory buffer to a file pointer. This */
1068
+ /* simply involves escaping newlines. */
1069
+ /* */
1070
+ /***************************************************************/
1071
+ void OutputLine(FILE *fp)
1072
+ {
1073
+ char const *s = CurLine;
1074
+ char c = 0;
1075
+
1076
+ while (*s) {
1077
+ if (*s == '\n') putc('\\', fp);
1078
+ putc(*s, fp);
1079
+ c = *s++;
1080
+ }
1081
+ if (c != '\n') putc('\n', fp);
1082
+ }
1083
+
1084
+ /***************************************************************/
1085
+ /* */
1086
+ /* CreateParser */
1087
+ /* */
1088
+ /* Create a parser given a string buffer */
1089
+ /* */
1090
+ /***************************************************************/
1091
+ void CreateParser(char const *s, ParsePtr p)
1092
+ {
1093
+ p->text = s;
1094
+ p->pos = s;
1095
+ p->isnested = 0;
1096
+ p->epos = NULL;
1097
+ p->etext = NULL;
1098
+ p->allownested = 1;
1099
+ p->tokenPushed = NULL;
1100
+ p->expr_happened = 0;
1101
+ p->nonconst_expr = 0;
1102
+ DBufInit(&p->pushedToken);
1103
+ }
1104
+
1105
+ /***************************************************************/
1106
+ /* */
1107
+ /* DestroyParser */
1108
+ /* */
1109
+ /* Destroy a parser, freeing up resources used. */
1110
+ /* */
1111
+ /***************************************************************/
1112
+ void DestroyParser(ParsePtr p)
1113
+ {
1114
+ if (p->isnested && p->etext) {
1115
+ free((void *) p->etext);
1116
+ p->etext = NULL;
1117
+ p->isnested = 0;
1118
+ }
1119
+ DBufFree(&p->pushedToken);
1120
+ }
1121
+
1122
+ /***************************************************************/
1123
+ /* */
1124
+ /* PushToken - one level of token pushback. This is */
1125
+ /* on a per-parser basis. */
1126
+ /* */
1127
+ /***************************************************************/
1128
+ int PushToken(char const *tok, ParsePtr p)
1129
+ {
1130
+ DBufFree(&p->pushedToken);
1131
+ if (DBufPuts(&p->pushedToken, tok) != OK ||
1132
+ DBufPutc(&p->pushedToken, ' ') != OK) {
1133
+ DBufFree(&p->pushedToken);
1134
+ return E_NO_MEM;
1135
+ }
1136
+ p->tokenPushed = DBufValue(&p->pushedToken);
1137
+ return OK;
1138
+ }
1139
+
1140
+ /***************************************************************/
1141
+ /* */
1142
+ /* SystemDateTime */
1143
+ /* */
1144
+ /* Return the system date time in minutes past */
1145
+ /* 1990-01-01@00:00 */
1146
+ /* */
1147
+ /***************************************************************/
1148
+ int SystemDateTime(int realtime)
1149
+ {
1150
+ if (realtime) {
1151
+ return SystemDate(NULL, NULL, NULL) * MINUTES_PER_DAY + MinutesPastMidnight(1);
1152
+ } else {
1153
+ return DSEToday * MINUTES_PER_DAY + MinutesPastMidnight(0);
1154
+ }
1155
+ }
1156
+
1157
+ /***************************************************************/
1158
+ /* */
1159
+ /* SystemTime */
1160
+ /* */
1161
+ /* Return the system time in seconds past midnight */
1162
+ /* */
1163
+ /***************************************************************/
1164
+ int SystemTime(int realtime)
1165
+ {
1166
+ time_t now;
1167
+ struct tm const *t;
1168
+
1169
+ if (!realtime && (SysTime != -1)) return SysTime;
1170
+
1171
+ if (TestMode) {
1172
+ /* Pretend it's 7:00PM in test mode */
1173
+ return 19 * 3600;
1174
+ }
1175
+
1176
+ now = time(NULL);
1177
+ t = localtime(&now);
1178
+ return t->tm_hour * 3600L + t->tm_min * 60L +
1179
+ t->tm_sec;
1180
+ }
1181
+
1182
+ /***************************************************************/
1183
+ /* */
1184
+ /* MinutesPastMidnight */
1185
+ /* */
1186
+ /* Return the system time in minutes past midnight */
1187
+ /* */
1188
+ /***************************************************************/
1189
+ int MinutesPastMidnight(int realtime)
1190
+ {
1191
+ return (SystemTime(realtime) / 60);
1192
+ }
1193
+
1194
+
1195
+ /***************************************************************/
1196
+ /* */
1197
+ /* SystemDate */
1198
+ /* */
1199
+ /* Obtains today's date. Returns DSE date or -1 for */
1200
+ /* failure. (Failure happens if sys date is before BASE */
1201
+ /* year.) */
1202
+ /* */
1203
+ /***************************************************************/
1204
+ int SystemDate(int *y, int *m, int *d)
1205
+ {
1206
+ time_t now;
1207
+ struct tm const *t;
1208
+
1209
+ /* In test mode, always return 6 January 2025 */
1210
+ if (TestMode) {
1211
+ if (y) *y = 2025;
1212
+ if (m) *m = 0;
1213
+ if (d) *d = 6;
1214
+ return 12789; /* 2025-01-06 */
1215
+ }
1216
+
1217
+ now = time(NULL);
1218
+ t = localtime(&now);
1219
+
1220
+ if (d) *d = t->tm_mday;
1221
+ if (m) *m = t->tm_mon;
1222
+ if (y) *y = t->tm_year + 1900;
1223
+
1224
+ return DSE(t->tm_year+1900, t->tm_mon, t->tm_mday);
1225
+ }
1226
+
1227
+
1228
+ /***************************************************************/
1229
+ /* */
1230
+ /* DoIf - handle the IF command. */
1231
+ /* */
1232
+ /***************************************************************/
1233
+ int DoIf(ParsePtr p)
1234
+ {
1235
+ Value v;
1236
+ int r;
1237
+
1238
+ if (if_stack_full()) {
1239
+ return E_NESTED_IF;
1240
+ }
1241
+
1242
+ if (should_ignore_line()) {
1243
+ push_if(1, 1);
1244
+ return OK;
1245
+ } else {
1246
+ if ( (r = EvaluateExpr(p, &v)) ) {
1247
+ Eprint("%s", GetErr(r));
1248
+ push_if(1, 0);
1249
+ } else
1250
+ if (truthy(&v)) {
1251
+ push_if(1, !p->nonconst_expr);
1252
+ } else {
1253
+ push_if(0, !p->nonconst_expr);
1254
+ if (PurgeMode && !Hush) {
1255
+ PurgeEchoLine("%s\n", "#!P: The next IF evaluated false...");
1256
+ PurgeEchoLine("%s\n", "#!P: REM statements in IF block not checked for purging.");
1257
+ }
1258
+ }
1259
+ }
1260
+ return VerifyEoln(p);
1261
+ }
1262
+
1263
+
1264
+ /***************************************************************/
1265
+ /* */
1266
+ /* DoElse - handle the ELSE command. */
1267
+ /* */
1268
+ /***************************************************************/
1269
+ int DoElse(ParsePtr p)
1270
+ {
1271
+ int was_ignoring = should_ignore_line();
1272
+
1273
+ int r = encounter_else();
1274
+ if (PurgeMode && should_ignore_line() && !was_ignoring && !Hush) {
1275
+ PurgeEchoLine("%s\n", "#!P: The previous IF evaluated true.");
1276
+ PurgeEchoLine("%s\n", "#!P: REM statements in ELSE block not checked for purging");
1277
+ }
1278
+ if (r != OK) {
1279
+ return r;
1280
+ }
1281
+ return VerifyEoln(p);
1282
+ }
1283
+
1284
+ /***************************************************************/
1285
+ /* */
1286
+ /* DoEndif - handle the Endif command. */
1287
+ /* */
1288
+ /***************************************************************/
1289
+ int DoEndif(ParsePtr p)
1290
+ {
1291
+ int r = encounter_endif();
1292
+ if (r != OK) {
1293
+ return r;
1294
+ }
1295
+ return VerifyEoln(p);
1296
+ }
1297
+
1298
+ /***************************************************************/
1299
+ /* */
1300
+ /* DoIfTrig */
1301
+ /* */
1302
+ /* Handle the IFTRIG command. */
1303
+ /* */
1304
+ /***************************************************************/
1305
+ int DoIfTrig(ParsePtr p)
1306
+ {
1307
+ int r, err;
1308
+ Trigger trig;
1309
+ TimeTrig tim;
1310
+ int dse;
1311
+
1312
+
1313
+ if (if_stack_full()) {
1314
+ return E_NESTED_IF;
1315
+ }
1316
+
1317
+ if (should_ignore_line()) {
1318
+ push_if(1, 0);
1319
+ return OK;
1320
+ } else {
1321
+ if ( (r=ParseRem(p, &trig, &tim)) ) return r;
1322
+ if (trig.typ != NO_TYPE) return E_PARSE_ERR;
1323
+ EnterTimezone(trig.tz);
1324
+ dse = ComputeTrigger(get_scanfrom(&trig), &trig, &tim, &r, 1);
1325
+ ExitTimezone(trig.tz);
1326
+ if (r) {
1327
+ if (r != E_CANT_TRIG || !trig.maybe_uncomputable) {
1328
+ if (!Hush || r != E_RUN_DISABLED) {
1329
+ Eprint("%s", GetErr(r));
1330
+ }
1331
+ }
1332
+ push_if(0, 0);
1333
+ } else {
1334
+ if (dse >= 0) {
1335
+ dse = AdjustTriggerForTimeZone(&trig, dse, &tim, 1);
1336
+ }
1337
+ if (ShouldTriggerReminder(&trig, &tim, dse, &err)) {
1338
+ push_if(1, 0);
1339
+ } else {
1340
+ push_if(0, 0);
1341
+ if (PurgeMode && !Hush) {
1342
+ PurgeEchoLine("%s\n", "#!P: The next IFTRIG did not trigger.");
1343
+ PurgeEchoLine("%s\n", "#!P: REM statements in IFTRIG block not checked for purging.");
1344
+ }
1345
+ }
1346
+ }
1347
+ FreeTrig(&trig);
1348
+ }
1349
+ return OK;
1350
+ }
1351
+
1352
+
1353
+ /***************************************************************/
1354
+ /* */
1355
+ /* VerifyEoln */
1356
+ /* */
1357
+ /* Verify that current line contains no more tokens. */
1358
+ /* */
1359
+ /***************************************************************/
1360
+ int VerifyEoln(ParsePtr p)
1361
+ {
1362
+ int r;
1363
+
1364
+ DynamicBuffer buf;
1365
+ DBufInit(&buf);
1366
+
1367
+ if ( (r = ParseToken(p, &buf)) ) return r;
1368
+ if (*DBufValue(&buf) &&
1369
+ (*DBufValue(&buf) != '#') &&
1370
+ (*DBufValue(&buf) != ';')) {
1371
+ Eprint("%s: `%s'", GetErr(E_EXPECTING_EOL), DBufValue(&buf));
1372
+ DBufFree(&buf);
1373
+ return E_EXTRANEOUS_TOKEN;
1374
+ }
1375
+ DBufFree(&buf);
1376
+ return OK;
1377
+ }
1378
+
1379
+ /***************************************************************/
1380
+ /* */
1381
+ /* DoDebug */
1382
+ /* */
1383
+ /* Set the debug options under program control. */
1384
+ /* */
1385
+ /***************************************************************/
1386
+ static int DoDebug(ParsePtr p)
1387
+ {
1388
+ int err;
1389
+ int ch;
1390
+ int val=1;
1391
+
1392
+ while(1) {
1393
+ ch = ParseChar(p, &err, 0);
1394
+ if (err) return err;
1395
+ switch(ch) {
1396
+ case '#':
1397
+ case ';':
1398
+ case 0:
1399
+ return OK;
1400
+
1401
+ case ' ':
1402
+ case '\t':
1403
+ break;
1404
+
1405
+ case '+':
1406
+ val = 1;
1407
+ break;
1408
+
1409
+ case '-':
1410
+ val = 0;
1411
+ break;
1412
+
1413
+ case 'p':
1414
+ case 'P':
1415
+ if (val) DebugFlag |= DB_PUSHPOP;
1416
+ else DebugFlag &= ~DB_PUSHPOP;
1417
+ break;
1418
+
1419
+ case 'e':
1420
+ case 'E':
1421
+ if (val) DebugFlag |= DB_ECHO_LINE;
1422
+ else DebugFlag &= ~DB_ECHO_LINE;
1423
+ break;
1424
+
1425
+ case 'q':
1426
+ case 'Q':
1427
+ if (val) DebugFlag |= DB_TRANSLATE;
1428
+ else DebugFlag &= ~DB_TRANSLATE;
1429
+ break;
1430
+
1431
+ case 's':
1432
+ case 'S':
1433
+ if (val) DebugFlag |= DB_PARSE_EXPR;
1434
+ else DebugFlag &= ~DB_PARSE_EXPR;
1435
+ break;
1436
+
1437
+ case 'h':
1438
+ case 'H':
1439
+ if (val) DebugFlag |= DB_HASHSTATS;
1440
+ else DebugFlag &= ~DB_HASHSTATS;
1441
+ break;
1442
+
1443
+ case 'x':
1444
+ case 'X':
1445
+ if (val) DebugFlag |= DB_PRTEXPR;
1446
+ else DebugFlag &= ~DB_PRTEXPR;
1447
+ break;
1448
+
1449
+ case 't':
1450
+ case 'T':
1451
+ if (val) DebugFlag |= DB_PRTTRIG;
1452
+ else DebugFlag &= ~DB_PRTTRIG;
1453
+ break;
1454
+
1455
+ case 'v':
1456
+ case 'V':
1457
+ if (val) DebugFlag |= DB_DUMP_VARS;
1458
+ else DebugFlag &= ~DB_DUMP_VARS;
1459
+ break;
1460
+
1461
+ case 'l':
1462
+ case 'L':
1463
+ if (val) DebugFlag |= DB_PRTLINE;
1464
+ else DebugFlag &= ~DB_PRTLINE;
1465
+ break;
1466
+
1467
+ case 'f':
1468
+ case 'F':
1469
+ if (val) DebugFlag |= DB_TRACE_FILES;
1470
+ else DebugFlag &= ~DB_TRACE_FILES;
1471
+ break;
1472
+
1473
+ case 'n':
1474
+ case 'N':
1475
+ if (val) DebugFlag |= DB_NONCONST;
1476
+ else DebugFlag &= ~DB_NONCONST;
1477
+ break;
1478
+ case 'u':
1479
+ case 'U':
1480
+ if (val) DebugFlag |= DB_UNUSED_VARS;
1481
+ else DebugFlag &= ~DB_UNUSED_VARS;
1482
+ break;
1483
+ case 'z':
1484
+ case 'Z':
1485
+ if (val) DebugFlag |= DB_SWITCH_ZONE;
1486
+ else DebugFlag &= ~DB_SWITCH_ZONE;
1487
+ break;
1488
+ default:
1489
+ if (warning_level("05.02.03")) {
1490
+ Wprint(GetErr(M_BAD_DB_FLAG), ch);
1491
+ }
1492
+ break;
1493
+ }
1494
+ }
1495
+ }
1496
+
1497
+ /***************************************************************/
1498
+ /* */
1499
+ /* DoBanner */
1500
+ /* */
1501
+ /* Set the banner to be printed just before the first */
1502
+ /* reminder is issued. */
1503
+ /* */
1504
+ /***************************************************************/
1505
+ static int DoBanner(ParsePtr p)
1506
+ {
1507
+ int err;
1508
+ int c;
1509
+ DynamicBuffer buf;
1510
+
1511
+ DBufInit(&buf);
1512
+ c = ParseChar(p, &err, 0);
1513
+ if (err) return err;
1514
+ while (isempty(c)) {
1515
+ c = ParseChar(p, &err, 0);
1516
+ if (err) return err;
1517
+ }
1518
+ if (!c) return E_EOLN;
1519
+
1520
+ while(c) {
1521
+ if (DBufPutc(&buf, c) != OK) return E_NO_MEM;
1522
+ c = ParseChar(p, &err, 0);
1523
+ if (err) {
1524
+ DBufFree(&buf);
1525
+ return err;
1526
+ }
1527
+ }
1528
+ DBufFree(&Banner);
1529
+
1530
+ err = DBufPuts(&Banner, DBufValue(&buf));
1531
+ DBufFree(&buf);
1532
+ return err;
1533
+ }
1534
+
1535
+ /***************************************************************/
1536
+ /* */
1537
+ /* DoRun */
1538
+ /* */
1539
+ /* Enable or disable the RUN command under program control */
1540
+ /* */
1541
+ /***************************************************************/
1542
+ int DoRun(ParsePtr p)
1543
+ {
1544
+ int r;
1545
+
1546
+ DynamicBuffer buf;
1547
+ DBufInit(&buf);
1548
+
1549
+ if ( (r=ParseToken(p, &buf)) ) return r;
1550
+
1551
+ /* Only allow RUN ON in top-level script */
1552
+ if (! strcasecmp(DBufValue(&buf), "ON")) {
1553
+ if (TopLevel()) RunDisabled &= ~RUN_SCRIPT;
1554
+ }
1555
+ /* But allow RUN OFF anywhere */
1556
+ else if (! strcasecmp(DBufValue(&buf), "OFF"))
1557
+ RunDisabled |= RUN_SCRIPT;
1558
+ else {
1559
+ DBufFree(&buf);
1560
+ return E_PARSE_ERR;
1561
+ }
1562
+ DBufFree(&buf);
1563
+
1564
+ return VerifyEoln(p);
1565
+ }
1566
+
1567
+ /***************************************************************/
1568
+ /* */
1569
+ /* DoExpr */
1570
+ /* */
1571
+ /* Enable or disable expression evaluation */
1572
+ /* */
1573
+ /***************************************************************/
1574
+ int DoExpr(ParsePtr p)
1575
+ {
1576
+ int r;
1577
+
1578
+ DynamicBuffer buf;
1579
+ DBufInit(&buf);
1580
+
1581
+ if ( (r=ParseToken(p, &buf)) ) return r;
1582
+
1583
+ /* Only allow EXPR ON in top-level script */
1584
+ if (! strcasecmp(DBufValue(&buf), "ON")) {
1585
+ if (TopLevel()) ExpressionEvaluationDisabled = 0;
1586
+ }
1587
+ /* But allow EXPR OFF anywhere */
1588
+ else if (! strcasecmp(DBufValue(&buf), "OFF"))
1589
+ ExpressionEvaluationDisabled = 1;
1590
+ else {
1591
+ DBufFree(&buf);
1592
+ return E_PARSE_ERR;
1593
+ }
1594
+ DBufFree(&buf);
1595
+
1596
+ return VerifyEoln(p);
1597
+ }
1598
+
1599
+ /***************************************************************/
1600
+ /* */
1601
+ /* DoFlush */
1602
+ /* */
1603
+ /* Flush stdout and stderr */
1604
+ /* */
1605
+ /***************************************************************/
1606
+ int DoFlush(ParsePtr p)
1607
+ {
1608
+ fflush(stdout);
1609
+ fflush(stderr);
1610
+ return VerifyEoln(p);
1611
+ }
1612
+
1613
+ /***************************************************************/
1614
+ /* */
1615
+ /* DoExit */
1616
+ /* */
1617
+ /* Handle the EXIT command. */
1618
+ /* */
1619
+ /***************************************************************/
1620
+ void DoExit(ParsePtr p)
1621
+ {
1622
+ int r;
1623
+ Value v;
1624
+
1625
+ if (PurgeMode) return;
1626
+
1627
+ if (JSONMode) {
1628
+ if (JSONLinesEmitted) {
1629
+ printf("}\n");
1630
+ }
1631
+ /* Close the reminder list */
1632
+ printf("]\n");
1633
+ }
1634
+ fflush(stdout);
1635
+ fflush(stderr);
1636
+ r = EvaluateExpr(p, &v);
1637
+ if (r || v.type != INT_TYPE) exit(99);
1638
+ exit(v.v.val);
1639
+ }
1640
+
1641
+ /***************************************************************/
1642
+ /* */
1643
+ /* DoErrMsg */
1644
+ /* */
1645
+ /* Issue an error message under program control. */
1646
+ /* */
1647
+ /***************************************************************/
1648
+ int DoErrMsg(ParsePtr p)
1649
+ {
1650
+ TimeTrig tt;
1651
+ Trigger t;
1652
+ int r;
1653
+ char const *s;
1654
+
1655
+ DynamicBuffer buf;
1656
+
1657
+ if (PurgeMode) return OK;
1658
+
1659
+ DBufInit(&buf);
1660
+ t.typ = MSG_TYPE;
1661
+ tt.ttime = SystemTime(0) / 60;
1662
+ if ( (r=DoSubst(p, &buf, &t, &tt, DSEToday, NORMAL_MODE)) ) {
1663
+ return r;
1664
+ }
1665
+ s = DBufValue(&buf);
1666
+ while (isempty(*s)) s++;
1667
+ fprintf(ErrFp, "%s\n", s);
1668
+ DBufFree(&buf);
1669
+ return OK;
1670
+ }
1671
+
1672
+ /***************************************************************/
1673
+ /* */
1674
+ /* CalcMinsFromUTC */
1675
+ /* */
1676
+ /* Attempt to calculate the minutes from UTC for a specific */
1677
+ /* date. */
1678
+ /* */
1679
+ /***************************************************************/
1680
+
1681
+ /* The array FoldArray[2][7] contains sample years which begin
1682
+ on the specified weekday. For example, FoldArray[0][2] is a
1683
+ non-leap year beginning on Wednesday, and FoldArray[1][5] is a
1684
+ leap year beginning on Saturday. Used to fold back dates which
1685
+ are too high for the standard Unix representation.
1686
+ NOTE: This implies that you cannot set BASE > 2012!!!!! */
1687
+ int FoldArray[2][7] = {
1688
+ {2035, 2030, 2031, 2026, 2027, 2033, 2034},
1689
+ {2024, 2036, 2020, 2032, 2016, 2028, 2012}
1690
+ };
1691
+
1692
+ int CalcMinsFromUTC(int dse, int tim, int *mins, int *isdst)
1693
+ {
1694
+
1695
+ /* Convert dse and tim to an Unix tm struct */
1696
+ int yr, mon, day;
1697
+ int tdiff;
1698
+ struct tm local, utc;
1699
+ struct tm const * temp;
1700
+ time_t loc_t, utc_t;
1701
+ int isdst_tmp;
1702
+
1703
+ FromDSE(dse, &yr, &mon, &day);
1704
+
1705
+ /* If the year is greater than 2037, some Unix machines have problems.
1706
+ Fold it back to a "similar" year and trust that the UTC calculations
1707
+ are still valid... */
1708
+ if (yr > 2037 && (FoldYear || (sizeof(time_t) < (64/CHAR_BIT)))) {
1709
+ dse = DSE(yr, 0, 1);
1710
+ yr = FoldArray[IsLeapYear(yr)][dse%7];
1711
+ }
1712
+ local.tm_sec = 0;
1713
+ local.tm_min = tim % 60;
1714
+ local.tm_hour = tim / 60;
1715
+
1716
+
1717
+ local.tm_mday = day;
1718
+ local.tm_mon = mon;
1719
+ local.tm_year = yr-1900;
1720
+ local.tm_isdst = -1; /* We don't know whether or not dst is in effect */
1721
+
1722
+
1723
+ /* Horrible contortions to get minutes from UTC portably */
1724
+ loc_t = mktime(&local);
1725
+ if (loc_t == -1) return 1;
1726
+ isdst_tmp = local.tm_isdst;
1727
+ local.tm_isdst = 0;
1728
+ loc_t = mktime(&local);
1729
+ if (loc_t == -1) return 1;
1730
+ temp = gmtime(&loc_t);
1731
+ utc = *temp;
1732
+ utc.tm_isdst = 0;
1733
+ utc_t = mktime(&utc);
1734
+ if (utc_t == -1) return 1;
1735
+ /* Compute difference between local time and UTC in seconds.
1736
+ Be careful, since time_t might be unsigned. */
1737
+
1738
+ tdiff = (int) difftime(loc_t, utc_t);
1739
+ if (isdst_tmp) tdiff += 60*60;
1740
+ if (mins) *mins = (int)(tdiff / 60);
1741
+ if (isdst) *isdst = isdst_tmp;
1742
+ return 0;
1743
+ }
1744
+
1745
+ static char const *OutputEscapeSequences(char const *s, int print, DynamicBuffer *output)
1746
+ {
1747
+ while (*s == 0x1B && *(s+1) == '[') {
1748
+ if (print) OUTPUT(*s);
1749
+ s++;
1750
+ if (print) OUTPUT(*s);
1751
+ s++;
1752
+ while (*s && (*s < 0x40 || *s > 0x7E)) {
1753
+ if (print) OUTPUT(*s);
1754
+ s++;
1755
+ }
1756
+ if (*s) {
1757
+ if (print) OUTPUT(*s);
1758
+ s++;
1759
+ }
1760
+ }
1761
+ return s;
1762
+ }
1763
+
1764
+ #define ISWBLANK(c) (iswspace(c) && (c) != '\n')
1765
+ static wchar_t const *OutputEscapeSequencesWS(wchar_t const *s, int print, DynamicBuffer *output)
1766
+ {
1767
+ while (*s == 0x1B && *(s+1) == '[') {
1768
+ if (print) PutWideChar(*s, output);
1769
+ s++;
1770
+ if (print) PutWideChar(*s, output);
1771
+ s++;
1772
+ while (*s && (*s < 0x40 || *s > 0x7E)) {
1773
+ if (print) PutWideChar(*s, output);
1774
+ s++;
1775
+ }
1776
+ if (*s) {
1777
+ if (print) PutWideChar(*s, output);
1778
+ s++;
1779
+ }
1780
+ }
1781
+ return s;
1782
+ }
1783
+
1784
+
1785
+ static void
1786
+ FillParagraphWCAux(wchar_t const *s, DynamicBuffer *output)
1787
+ {
1788
+ int line = 0;
1789
+ int i, j;
1790
+ int doublespace = 1;
1791
+ int pendspace;
1792
+ int len;
1793
+ wchar_t const *t;
1794
+
1795
+ int roomleft;
1796
+ /* Start formatting */
1797
+ while(1) {
1798
+
1799
+ /* If it's a carriage return, output it and start new paragraph */
1800
+ if (*s == '\n') {
1801
+ OUTPUT('\n');
1802
+ s++;
1803
+ line = 0;
1804
+ while(ISWBLANK(*s)) s++;
1805
+ continue;
1806
+ }
1807
+ if (!*s) {
1808
+ return;
1809
+ }
1810
+ /* Over here, we're at the beginning of a line. Emit the correct
1811
+ number of spaces */
1812
+ j = line ? SubsIndent : FirstIndent;
1813
+ for (i=0; i<j; i++) {
1814
+ OUTPUT(' ');
1815
+ }
1816
+
1817
+ /* Calculate the amount of room left on this line */
1818
+ roomleft = FormWidth - j;
1819
+ pendspace = 0;
1820
+
1821
+ /* Emit words until the next one won't fit */
1822
+ while(1) {
1823
+ while(ISWBLANK(*s)) s++;
1824
+ if (*s == '\n') break;
1825
+ while(1) {
1826
+ t = s;
1827
+ s = OutputEscapeSequencesWS(s, 1, output);
1828
+ if (s == t) break;
1829
+ while(ISWBLANK(*s)) s++;
1830
+ }
1831
+ t = s;
1832
+ len = 0;
1833
+ while(*s && !iswspace(*s)) {
1834
+ if (*s == 0x1B && *(s+1) == '[') {
1835
+ s = OutputEscapeSequencesWS(s, 0, output);
1836
+ continue;
1837
+ }
1838
+ len += wcwidth(*s);
1839
+ s++;
1840
+ }
1841
+ if (s == t) {
1842
+ return;
1843
+ }
1844
+ if (!pendspace || len+pendspace <= roomleft) {
1845
+ for (i=0; i<pendspace; i++) {
1846
+ OUTPUT(' ');
1847
+ }
1848
+ while(t < s) {
1849
+ PutWideChar(*t, output);
1850
+ if (strchr(EndSent, *t)) doublespace = 2;
1851
+ else if (!strchr(EndSentIg, *t)) doublespace = 1;
1852
+ t++;
1853
+ }
1854
+ } else {
1855
+ s = t;
1856
+ OUTPUT('\n');
1857
+ line++;
1858
+ break;
1859
+ }
1860
+ roomleft -= len+doublespace;
1861
+ pendspace = doublespace;
1862
+ }
1863
+ }
1864
+ }
1865
+
1866
+ static int
1867
+ FillParagraphWC(char const *s, DynamicBuffer *output)
1868
+ {
1869
+ size_t len;
1870
+ wchar_t *buf;
1871
+
1872
+ len = mbstowcs(NULL, s, 0);
1873
+ if (len == (size_t) -1) return E_NO_MEM;
1874
+ buf = calloc(len+1, sizeof(wchar_t));
1875
+ if (!buf) return E_NO_MEM;
1876
+ (void) mbstowcs(buf, s, len+1);
1877
+ FillParagraphWCAux(buf, output);
1878
+ free(buf);
1879
+ return OK;
1880
+ }
1881
+
1882
+ /***************************************************************/
1883
+ /* */
1884
+ /* FillParagraph */
1885
+ /* */
1886
+ /* Write a string to standard output, formatting it as a */
1887
+ /* paragraph according to the FirstIndent, FormWidth and */
1888
+ /* SubsIndent variables. Spaces are gobbled. Double-spaces */
1889
+ /* are inserted after '.', '?' and '!'. Newlines in the */
1890
+ /* source are treated as paragraph breaks. */
1891
+ /* */
1892
+ /***************************************************************/
1893
+
1894
+ /* A macro safe ONLY if used with arg with no side effects! */
1895
+ #define ISBLANK(c) (isspace(c) && (c) != '\n')
1896
+
1897
+ void FillParagraph(char const *url, char const *s, DynamicBuffer *output)
1898
+ {
1899
+
1900
+ int line = 0;
1901
+ int i, j;
1902
+ int doublespace = 1;
1903
+ int pendspace;
1904
+ int len;
1905
+ char const *t;
1906
+
1907
+ int roomleft;
1908
+ if (!s || !*s) return;
1909
+
1910
+ /* Skip leading spaces */
1911
+ while(ISBLANK(*s)) s++;
1912
+ if (!*s) return;
1913
+
1914
+ if (url) {
1915
+ printf("\x1B]8;;%s\x1B\\", url);
1916
+ }
1917
+
1918
+ if (FillParagraphWC(s, output) == OK) {
1919
+ if (url) {
1920
+ printf("\x1B]8;;\x1B\\");
1921
+ }
1922
+ return;
1923
+ }
1924
+
1925
+ /* Start formatting */
1926
+ while(1) {
1927
+
1928
+ /* If it's a carriage return, output it and start new paragraph */
1929
+ if (*s == '\n') {
1930
+ OUTPUT('\n');
1931
+ s++;
1932
+ line = 0;
1933
+ while(ISBLANK(*s)) s++;
1934
+ continue;
1935
+ }
1936
+ if (!*s) {
1937
+ if (url) {
1938
+ printf("\x1B]8;;\x1B\\");
1939
+ }
1940
+ return;
1941
+ }
1942
+ /* Over here, we're at the beginning of a line. Emit the correct
1943
+ number of spaces */
1944
+ j = line ? SubsIndent : FirstIndent;
1945
+ for (i=0; i<j; i++) {
1946
+ OUTPUT(' ');
1947
+ }
1948
+
1949
+ /* Calculate the amount of room left on this line */
1950
+ roomleft = FormWidth - j;
1951
+ pendspace = 0;
1952
+
1953
+ /* Emit words until the next one won't fit */
1954
+ while(1) {
1955
+ while(ISBLANK(*s)) s++;
1956
+ if (*s == '\n') break;
1957
+ while(1) {
1958
+ t = s;
1959
+ s = OutputEscapeSequences(s, 1, output);
1960
+ if (s == t) break;
1961
+ while(ISBLANK(*s)) s++;
1962
+ }
1963
+ t = s;
1964
+ len = 0;
1965
+ while(*s && !isspace(*s)) {
1966
+ if (*s == 0x1B && *(s+1) == '[') {
1967
+ s = OutputEscapeSequences(s, 0, output);
1968
+ continue;
1969
+ }
1970
+ s++;
1971
+ len++;
1972
+ }
1973
+ if (s == t) {
1974
+ if (url) {
1975
+ printf("\x1B]8;;\x1B\\");
1976
+ }
1977
+ return;
1978
+ }
1979
+ if (!pendspace || len+pendspace <= roomleft) {
1980
+ for (i=0; i<pendspace; i++) {
1981
+ OUTPUT(' ');
1982
+ }
1983
+ while(t < s) {
1984
+ OUTPUT(*t);
1985
+ if (strchr(EndSent, *t)) doublespace = 2;
1986
+ else if (!strchr(EndSentIg, *t)) doublespace = 1;
1987
+ t++;
1988
+ }
1989
+ } else {
1990
+ s = t;
1991
+ OUTPUT('\n');
1992
+ line++;
1993
+ break;
1994
+ }
1995
+ roomleft -= len+doublespace;
1996
+ pendspace = doublespace;
1997
+ }
1998
+ }
1999
+ }
2000
+
2001
+ /***************************************************************/
2002
+ /* */
2003
+ /* LocalToUTC */
2004
+ /* */
2005
+ /* Convert a local date/time to a UTC date/time. */
2006
+ /* */
2007
+ /***************************************************************/
2008
+ void LocalToUTC(int locdate, int loctime, int *utcdate, int *utctime)
2009
+ {
2010
+ int diff;
2011
+ int dummy;
2012
+
2013
+ if (!CalculateUTC || CalcMinsFromUTC(locdate, loctime, &diff, &dummy))
2014
+ diff=MinsFromUTC;
2015
+
2016
+ loctime -= diff;
2017
+ if (loctime < 0) {
2018
+ loctime += MINUTES_PER_DAY;
2019
+ locdate--;
2020
+ } else if (loctime >= MINUTES_PER_DAY) {
2021
+ loctime -= MINUTES_PER_DAY;
2022
+ locdate++;
2023
+ }
2024
+ *utcdate = locdate;
2025
+ *utctime = loctime;
2026
+ }
2027
+
2028
+ /***************************************************************/
2029
+ /* */
2030
+ /* UTCToLocal */
2031
+ /* */
2032
+ /* Convert a UTC date/time to a local date/time. */
2033
+ /* */
2034
+ /***************************************************************/
2035
+ void UTCToLocal(int utcdate, int utctime, int *locdate, int *loctime)
2036
+ {
2037
+ int diff;
2038
+ int dummy;
2039
+
2040
+ /* Hack -- not quite right when DST changes. */
2041
+ if (!CalculateUTC || CalcMinsFromUTC(utcdate, utctime, &diff, &dummy))
2042
+ diff=MinsFromUTC;
2043
+
2044
+ utctime += diff;
2045
+ if (utctime < 0) {
2046
+ utctime += MINUTES_PER_DAY;
2047
+ utcdate--;
2048
+ } else if (utctime >= MINUTES_PER_DAY) {
2049
+ utctime -= MINUTES_PER_DAY;
2050
+ utcdate++;
2051
+ }
2052
+ *locdate = utcdate;
2053
+ *loctime = utctime;
2054
+ }
2055
+
2056
+ /***************************************************************/
2057
+ /* */
2058
+ /* SigIntHandler */
2059
+ /* */
2060
+ /* For debugging purposes, when sent a SIGINT, we print the */
2061
+ /* contents of the queue. This does NOT work when the -f */
2062
+ /* command-line flag is supplied. */
2063
+ /* */
2064
+ /***************************************************************/
2065
+ static sig_atomic_t got_sigint = 0;
2066
+
2067
+ void
2068
+ SigIntHandler(int d)
2069
+ {
2070
+ UNUSED(d);
2071
+ got_sigint = 1;
2072
+ }
2073
+
2074
+ int
2075
+ GotSigInt(void)
2076
+ {
2077
+ if (got_sigint) {
2078
+ got_sigint = 0;
2079
+ return 1;
2080
+ }
2081
+ return 0;
2082
+ }
2083
+
2084
+ void
2085
+ AppendTag(DynamicBuffer *buf, char const *s)
2086
+ {
2087
+ if (*(DBufValue(buf))) {
2088
+ DBufPutc(buf, ',');
2089
+ }
2090
+ DBufPuts(buf, s);
2091
+ }
2092
+
2093
+ void
2094
+ FreeTrig(Trigger *t)
2095
+ {
2096
+ DBufFree(&(t->tags));
2097
+ if (t->infos) {
2098
+ FreeTrigInfoChain(t->infos);
2099
+ }
2100
+ if (t->tz) {
2101
+ free( (void *) t->tz);
2102
+ }
2103
+ t->tz = NULL;
2104
+ t->infos = NULL;
2105
+ }
2106
+
2107
+ static void
2108
+ ClearLastTriggers(void)
2109
+ {
2110
+ LastTrigger.expired = 0;
2111
+ LastTrigger.wd = NO_WD;
2112
+ LastTrigger.d = NO_DAY;
2113
+ LastTrigger.m = NO_MON;
2114
+ LastTrigger.y = NO_YR;
2115
+ LastTrigger.back = NO_BACK;
2116
+ LastTrigger.delta = NO_DELTA;
2117
+ LastTrigger.rep = NO_REP;
2118
+ LastTrigger.localomit = NO_WD;
2119
+ LastTrigger.skip = NO_SKIP;
2120
+ LastTrigger.until = NO_UNTIL;
2121
+ LastTrigger.typ = NO_TYPE;
2122
+ LastTrigger.once = NO_ONCE;
2123
+ LastTrigger.scanfrom = NO_DATE;
2124
+ LastTrigger.from = NO_DATE;
2125
+ LastTrigger.priority = DefaultPrio;
2126
+ LastTrigger.sched[0] = 0;
2127
+ LastTrigger.warn[0] = 0;
2128
+ LastTrigger.omitfunc[0] = 0;
2129
+ LastTrigger.passthru[0] = 0;
2130
+ LastTrigger.is_todo = 0;
2131
+ LastTrigger.complete_through = NO_DATE;
2132
+ LastTrigger.max_overdue = -1;
2133
+ FreeTrig(&LastTrigger);
2134
+
2135
+ LastTimeTrig.ttime = NO_TIME;
2136
+ LastTimeTrig.ttime_orig = NO_TIME;
2137
+ LastTimeTrig.delta = NO_DELTA;
2138
+ LastTimeTrig.rep = NO_REP;
2139
+ LastTimeTrig.duration = NO_TIME;
2140
+
2141
+ }
2142
+
2143
+ void
2144
+ SaveAllTriggerInfo(Trigger const *t, TimeTrig const *tt, int trigdate, int trigtime, int valid)
2145
+ {
2146
+ SaveLastTrigger(t);
2147
+ SaveLastTimeTrig(tt);
2148
+ if (trigdate != -1) {
2149
+ LastTriggerDate = trigdate;
2150
+ LastTrigValid = valid;
2151
+ }
2152
+ LastTriggerTime = trigtime;
2153
+ }
2154
+
2155
+ void
2156
+ SaveLastTrigger(Trigger const *t)
2157
+ {
2158
+ FreeTrig(&LastTrigger);
2159
+ memcpy(&LastTrigger, t, sizeof(LastTrigger));
2160
+
2161
+ /* DON'T hang on to the invalid info chain! */
2162
+ LastTrigger.infos = NULL;
2163
+ DBufInit(&(LastTrigger.tags));
2164
+
2165
+ if (LastTrigger.tz) {
2166
+ LastTrigger.tz = strdup(LastTrigger.tz);
2167
+ }
2168
+ DBufPuts(&(LastTrigger.tags), DBufValue(&(t->tags)));
2169
+ TrigInfo *cur = t->infos;
2170
+ while(cur) {
2171
+ AppendTrigInfo(&LastTrigger, cur->info);
2172
+ cur = cur->next;
2173
+ }
2174
+ }
2175
+
2176
+ static void
2177
+ SaveLastTimeTrig(TimeTrig const *t)
2178
+ {
2179
+ memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig));
2180
+ }
2181
+
2182
+ /* Wrapper to ignore warnings about ignoring return value of system()
2183
+ Also redirects stdin and stdout to /dev/null for queued reminders */
2184
+
2185
+ void
2186
+ System(char const *cmd, int is_queued)
2187
+ {
2188
+ pid_t kid;
2189
+ int fd;
2190
+ int status;
2191
+ int do_exit = 0;
2192
+
2193
+ if (is_queued && IsServerMode()) {
2194
+ do_exit = 1;
2195
+ /* Server mode... redirect stdin and stdout to /dev/null */
2196
+ kid = fork();
2197
+ if (kid == (pid_t) -1) {
2198
+ /* Fork failed... nothing we can do */
2199
+ return;
2200
+ } else if (kid == 0) {
2201
+ /* In the child */
2202
+ (void) close(STDIN_FILENO);
2203
+ (void) close(STDOUT_FILENO);
2204
+ fd = open("/dev/null", O_RDONLY);
2205
+ if (fd >= 0 && fd != STDIN_FILENO) {
2206
+ dup2(fd, STDIN_FILENO);
2207
+ close(STDIN_FILENO);
2208
+ }
2209
+ fd = open("/dev/null", O_WRONLY);
2210
+ if (fd >= 0 && fd != STDOUT_FILENO) {
2211
+ dup2(fd, STDOUT_FILENO);
2212
+ close(STDOUT_FILENO);
2213
+ }
2214
+ } else {
2215
+ /* In the parent */
2216
+ while (waitpid(kid, &status, 0) != kid) /* continue */ ;
2217
+ return;
2218
+ }
2219
+ }
2220
+ /* This is the child process or original if we never forked */
2221
+ if (JSONMode) {
2222
+ (void) system_to_stderr(cmd);
2223
+ } else {
2224
+ (void) system1(cmd);
2225
+ }
2226
+ if (do_exit) {
2227
+ /* In the child process, so exit! */
2228
+ exit(0);
2229
+ }
2230
+ return;
2231
+ }
2232
+
2233
+ char const *
2234
+ get_day_name(int wkday)
2235
+ {
2236
+ if (wkday < 0 || wkday > 6) {
2237
+ return "INVALID_WKDAY";
2238
+ }
2239
+ return tr(DayName[wkday]);
2240
+ }
2241
+
2242
+ char const *
2243
+ get_month_name(int mon)
2244
+ {
2245
+ if (mon < 0 || mon > 11) {
2246
+ return "INVALID_MON";
2247
+ }
2248
+ return tr(MonthName[mon]);
2249
+ }
2250
+
2251
+ static int GetOnceDateFromFile(void)
2252
+ {
2253
+ FILE *fp;
2254
+
2255
+ int once_date = 0;
2256
+
2257
+ fp = fopen(OnceFile, "r");
2258
+ if (fp) {
2259
+ if (fscanf(fp, "%d", &once_date) != 1) {
2260
+ once_date = 0;
2261
+ }
2262
+ fclose(fp);
2263
+ }
2264
+ /* Save today to file */
2265
+ fp = fopen(OnceFile, "w");
2266
+ if (!fp) {
2267
+ Wprint(tr("Warning: Unable to save ONCE timestamp to %s: %s"),
2268
+ OnceFile, strerror(errno));
2269
+ return once_date;
2270
+ }
2271
+ fprintf(fp, "%d\n# This is a timestamp file used by Remind to track ONCE reminders.\n# Do not edit or delete it.\n", DSEToday);
2272
+ fclose(fp);
2273
+ return once_date;
2274
+ }
2275
+
2276
+ int GetOnceDate(void)
2277
+ {
2278
+ ProcessedOnce = 1;
2279
+ if (IgnoreOnce || !OnceFile || !*OnceFile) {
2280
+ return FileAccessDate;
2281
+ }
2282
+ if (OnceDate < 0) {
2283
+ OnceDate = GetOnceDateFromFile();
2284
+ }
2285
+ return OnceDate;
2286
+ }
2287
+
2288
+ char const *GetEnglishErr(int r)
2289
+ {
2290
+ if (r < 0 || r >= NumErrs) {
2291
+ r = E_SWERR;
2292
+ }
2293
+ return ErrMsg[r];
2294
+ }
2295
+
2296
+ char const *GetErr(int r)
2297
+ {
2298
+ char const *msg;
2299
+
2300
+ if (r < 0 || r >= NumErrs) {
2301
+ r = E_SWERR;
2302
+ }
2303
+
2304
+ msg = GetTranslatedString(ErrMsg[r]);
2305
+ if (!msg) {
2306
+ return ErrMsg[r];
2307
+ }
2308
+
2309
+ return msg;
2310
+ }