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,2389 @@
1
+ /***************************************************************/
2
+ /* */
3
+ /* DOREM.C */
4
+ /* */
5
+ /* Contains routines for parsing reminders and evaluating */
6
+ /* triggers. Also contains routines for parsing OMIT */
7
+ /* commands. */
8
+ /* */
9
+ /* This file is part of REMIND. */
10
+ /* Copyright (C) 1992-2026 by Dianne Skoll */
11
+ /* SPDX-License-Identifier: GPL-2.0-only */
12
+ /* */
13
+ /***************************************************************/
14
+
15
+ #include "config.h"
16
+ #include <stdio.h>
17
+ #include <ctype.h>
18
+ #include <string.h>
19
+
20
+ #include <stdlib.h>
21
+ #include <time.h>
22
+
23
+ #include "types.h"
24
+ #include "globals.h"
25
+ #include "err.h"
26
+ #include "protos.h"
27
+
28
+ static int ParseTimeTrig (ParsePtr s, TimeTrig *tim);
29
+ static int ParseLocalOmit (ParsePtr s, Trigger *t);
30
+ static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
31
+ static int ParsePriority (ParsePtr s, Trigger *t);
32
+ static int ParseUntil (ParsePtr s, Trigger *t, int type);
33
+ static int ShouldTriggerBasedOnWarn (Trigger const *t, int dse, int *err);
34
+ static int ComputeTrigDuration(TimeTrig const *t);
35
+ static int ShouldQueueReminder(Trigger const *t, TimeTrig const *tim, int dse);
36
+
37
+ static int CalledEnterTimezone = 0;
38
+
39
+ int AdjustTriggerForTimeZone(Trigger *trig, int dse, TimeTrig *tim, int debug_ok)
40
+ {
41
+ int y, m, d, hour, minute;
42
+ int r;
43
+ struct tm tm;
44
+ if (!trig->tz || dse < 0) {
45
+ /* Already local time or did not compute trigger date - no adjustments needed */
46
+ return dse;
47
+ }
48
+ FromDSE(dse, &y, &m, &d);
49
+ hour = tim->ttime_orig / 60;
50
+ minute = tim->ttime_orig % 60;
51
+
52
+ r = tz_convert(y, m, d, hour, minute, trig->tz, LocalTimeZone, &tm);
53
+ if (r != 1) {
54
+ Wprint(tr("Error adjusting trigger to local time zone"));
55
+ return dse;
56
+ }
57
+
58
+ dse = DSE(tm.tm_year+1900, tm.tm_mon, tm.tm_mday);
59
+ tim->ttime = tm.tm_hour * 60 + tm.tm_min;
60
+ /* Adjust eventstart also */
61
+ trig->eventstart = dse * MINUTES_PER_DAY + tim->ttime;
62
+ SaveAllTriggerInfo(trig, tim, dse, tim->ttime, 1);
63
+ if (debug_ok && (DebugFlag & DB_PRTTRIG)) {
64
+ fprintf(ErrFp, "%s(%s): Trig(tz_adj %s) = %s, %d %s, %d AT %02d:%02d",
65
+ GetCurrentFilename(), line_range(LineNoStart, LineNo), trig->tz,
66
+ get_day_name(dse % 7), tm.tm_mday, get_month_name(tm.tm_mon),
67
+ 1900 + tm.tm_year, tim->ttime / 60, tim->ttime % 60);
68
+ if (tim->duration != NO_TIME) {
69
+ fprintf(ErrFp, " DURATION %02d:%02d",
70
+ (tim->duration / 60),
71
+ (tim->duration % 60));
72
+ }
73
+ fprintf(ErrFp, "\n");
74
+ }
75
+ return dse;
76
+ }
77
+
78
+ void ExitTimezone(char const *tz)
79
+ {
80
+ if (!CalledEnterTimezone) {
81
+ fprintf(stderr, "ExitTimezone called without EnterTimezone!!!\n");
82
+ abort();
83
+ }
84
+ CalledEnterTimezone = 0;
85
+ if (!tz || !*tz) {
86
+ /* Nothing to do */
87
+ return;
88
+ }
89
+ /* Revert to our local time zone */
90
+ (void) tz_set_tz(LocalTimeZone);
91
+
92
+ DSEToday = LocalDSEToday;
93
+ SysTime = LocalSysTime;
94
+ FromDSE(DSEToday, &CurYear, &CurMon, &CurDay);
95
+
96
+ if (DebugFlag & DB_SWITCH_ZONE) {
97
+ fprintf(stderr, "TZ exit %s: %04d-%02d-%02d %02d:%02d\n", tz,
98
+ CurYear, CurMon+1, CurDay, SysTime / 3600, (SysTime/60) % 60);
99
+ }
100
+ return;
101
+ }
102
+
103
+
104
+ void EnterTimezone(char const *tz)
105
+ {
106
+ struct tm tm;
107
+ int y, m, d;
108
+ time_t t;
109
+
110
+ if (CalledEnterTimezone) {
111
+ fprintf(stderr, "EnterTimezone called twice in a row!!!\n");
112
+ abort();
113
+ }
114
+
115
+ CalledEnterTimezone = 1;
116
+
117
+ if (!tz || !*tz) {
118
+ /* Stay in local timezone */
119
+ return;
120
+ }
121
+
122
+ FromDSE(LocalDSEToday, &y, &m, &d);
123
+ tm.tm_sec = 0;
124
+ tm.tm_min = (LocalSysTime/60) % 60;
125
+ tm.tm_hour = LocalSysTime / 3600;
126
+ tm.tm_mday = d;
127
+ tm.tm_mon = m;
128
+ tm.tm_year = y - 1900;
129
+ tm.tm_wday = 0; /* Ignored by mktime */
130
+ tm.tm_yday = 0; /* Ignored by mktime */
131
+ tm.tm_isdst = -1; /* Information not available */
132
+
133
+ t = mktime(&tm); /* Convert local time to seconds */
134
+
135
+ /* Set target timezone */
136
+ (void) tz_set_tz(tz);
137
+
138
+ /* Update our variables */
139
+ (void) localtime_r(&t, &tm);
140
+
141
+ SysTime = tm.tm_min * 60 + (tm.tm_hour * 3600);
142
+ CurDay = tm.tm_mday;
143
+ CurMon = tm.tm_mon;
144
+ CurYear = tm.tm_year + 1900;
145
+
146
+ DSEToday = DSE(CurYear, CurMon, CurDay);
147
+
148
+ /* Adjust DSEToday back by a day if midnight in our time zone requires it */
149
+ if (SysTime < LocalSysTime) {
150
+ DSEToday--;
151
+ FromDSE(DSEToday, &CurYear, &CurMon, &CurDay);
152
+ }
153
+
154
+ if (DebugFlag & DB_SWITCH_ZONE) {
155
+ fprintf(stderr, "TZ enter %s: %04d-%02d-%02d %02d:%02d\n", tz,
156
+ CurYear, CurMon+1, CurDay, SysTime / 3600, (SysTime/60) % 60);
157
+ }
158
+ }
159
+
160
+ void remove_trailing_newlines(DynamicBuffer *buf)
161
+ {
162
+ char *s = (char *) DBufValue(buf) + DBufLen(buf) - 1;
163
+ while (s >= DBufValue(buf)) {
164
+ if (*s == '\n') {
165
+ *s = 0;
166
+ s--;
167
+ } else {
168
+ break;
169
+ }
170
+ }
171
+ }
172
+ static int todo_filtered(Trigger const *t)
173
+ {
174
+ if (t->is_todo && TodoFilter == ONLY_EVENTS) return 1;
175
+ if (!t->is_todo && TodoFilter == ONLY_TODOS) return 1;
176
+ return 0;
177
+ }
178
+
179
+ static int
180
+ get_raw_scanfrom(Trigger const *t)
181
+ {
182
+ if (t->from != NO_DATE) {
183
+ if (t->from > DSEToday) return t->from;
184
+ return DSEToday;
185
+ }
186
+ if (t->scanfrom == NO_SCANFROM) return NO_SCANFROM;
187
+ if (t->scanfrom > 0) return t->scanfrom;
188
+
189
+ /* Relative SCANFROM is negative, so subtract from today() */
190
+ return DSEToday + t->scanfrom;
191
+ }
192
+
193
+ int
194
+ get_scanfrom(Trigger const *t)
195
+ {
196
+ int calmode = (DoSimpleCalendar || DoCalendar) ? 1 : 0;
197
+
198
+ /* TODOs are treated just like events in calendar mode */
199
+ if (!calmode && t->is_todo && t->from != NO_DATE) {
200
+ if (t->complete_through != NO_DATE) {
201
+ if (t->complete_through+1 > t->from) {
202
+ return t->complete_through+1;
203
+ } else {
204
+ return t->from;
205
+ }
206
+ } else {
207
+ return t->from;
208
+ }
209
+ }
210
+ if (get_raw_scanfrom(t) != NO_SCANFROM) {
211
+ if (!calmode && t->complete_through != NO_DATE) {
212
+ if (t->complete_through+1 > get_raw_scanfrom(t)) {
213
+ return t->complete_through+1;
214
+ } else {
215
+ return get_raw_scanfrom(t);
216
+ }
217
+ } else {
218
+ return get_raw_scanfrom(t);
219
+ }
220
+ }
221
+ if (!calmode) {
222
+ if (t->complete_through != NO_DATE) {
223
+ return t->complete_through+1;
224
+ }
225
+ if (t->is_todo) {
226
+ /* TODO with no COMPLETE-THROUGH.
227
+ Scan from the beginning of time */
228
+ return 0;
229
+ }
230
+ }
231
+ return DSEToday;
232
+ }
233
+
234
+ static int
235
+ ensure_expr_references_first_local_arg(expr_node *node)
236
+ {
237
+ expr_node *other;
238
+
239
+ if (!node) {
240
+ return 0;
241
+ }
242
+ if (node->type == N_LOCAL_VAR && node->u.arg == 0) {
243
+ return 1;
244
+ }
245
+ if (ensure_expr_references_first_local_arg(node->child)) {
246
+ return 1;
247
+ }
248
+ other = node->sibling;
249
+ while (other) {
250
+ if (ensure_expr_references_first_local_arg(other)) {
251
+ return 1;
252
+ }
253
+ other = other->sibling;
254
+ }
255
+ return 0;
256
+ }
257
+
258
+ static void
259
+ check_trigger_function(char const *fname, char const *type)
260
+ {
261
+ UserFunc *f;
262
+ if (!*fname) {
263
+ return;
264
+ }
265
+ f = FindUserFunc(fname);
266
+ if (!f) {
267
+ if (strcmp(type, "WARN")) {
268
+ /* Undefined WARN functions are diagnosed elsewhere... */
269
+ Wprint(tr("Undefined %s function: `%s'"), type, fname);
270
+ }
271
+ return;
272
+ }
273
+ if (f->nargs != 1) {
274
+ Wprint(tr("%s function `%s' defined at %s(%s) should take 1 argument but actually takes %d"), type, fname, f->filename, line_range(f->lineno_start, f->lineno), f->nargs);
275
+ return;
276
+ }
277
+ if (ensure_expr_references_first_local_arg(f->node)) {
278
+ return;
279
+ }
280
+ Wprint(tr("%s function `%s' defined at %s(%s) does not use its argument"), type, fname, f->filename, line_range(f->lineno_start, f->lineno));
281
+ }
282
+
283
+ static void
284
+ ensure_satnode_mentions_trigdate_aux(expr_node *node, int *mentioned)
285
+ {
286
+ char const *name;
287
+ expr_node *other;
288
+ UserFunc *f;
289
+
290
+ if (!node) {
291
+ return;
292
+ }
293
+ if (*mentioned) {
294
+ return;
295
+ }
296
+
297
+ if (node->type == N_BUILTIN_FUNC) {
298
+ name = node->u.builtin_func->name;
299
+ if (!strcmp(name, "trigdate") ||
300
+ !strcmp(name, "trigdatetime")) {
301
+ *mentioned = 1;
302
+ return;
303
+ }
304
+ } else if (node->type == N_SYSVAR) {
305
+ name = node->u.sysvar->name;
306
+ if (!strcasecmp(name, "T") ||
307
+ !strcasecmp(name, "Td") ||
308
+ !strcasecmp(name, "Tm") ||
309
+ !strcasecmp(name, "Tw") ||
310
+ !strcasecmp(name, "Ty")) {
311
+ *mentioned = 1;
312
+ return;
313
+ }
314
+ } else if (node->type == N_SHORT_USER_FUNC || node->type == N_USER_FUNC) {
315
+ if (node->type == N_SHORT_USER_FUNC) {
316
+ name = node->u.name;
317
+ } else {
318
+ name = node->u.value.v.str;
319
+ }
320
+ f = FindUserFunc(name);
321
+ if (f && !f->recurse_flag) {
322
+ f->recurse_flag = 1;
323
+ ensure_satnode_mentions_trigdate_aux(f->node, mentioned);
324
+ f->recurse_flag = 0;
325
+ if (*mentioned) {
326
+ return;
327
+ }
328
+ }
329
+ }
330
+ ensure_satnode_mentions_trigdate_aux(node->child, mentioned);
331
+ if (*mentioned) {
332
+ return;
333
+ }
334
+ other = node->sibling;
335
+ while (other) {
336
+ ensure_satnode_mentions_trigdate_aux(other, mentioned);
337
+ if (*mentioned) {
338
+ return;
339
+ }
340
+ other = other->sibling;
341
+ }
342
+ }
343
+
344
+ static void ensure_satnode_mentions_trigdate(expr_node *node)
345
+ {
346
+ int mentioned = 0;
347
+ char const *str;
348
+
349
+ /* Don't bother unless warning_level is 05.00.03 */
350
+ if (!warning_level("05.00.03")) {
351
+ return;
352
+ }
353
+ if (node->type == N_CONSTANT || node->type == N_SHORT_STR) {
354
+ if (node->type == N_CONSTANT) {
355
+ if (node->u.value.type == INT_TYPE) {
356
+ if (node->u.value.v.val == 0) {
357
+ Wprint(tr("SATISFY: constant 0 will never be true"));
358
+ }
359
+ return;
360
+ }
361
+ if (node->u.value.type != STR_TYPE) {
362
+ return;
363
+ }
364
+ str = node->u.value.v.str;
365
+ } else {
366
+ str = node->u.name;
367
+ }
368
+ if (!*str) {
369
+ Wprint(tr("SATISFY: constant \"\" will never be true"));
370
+ }
371
+ return;
372
+ }
373
+
374
+ ensure_satnode_mentions_trigdate_aux(node, &mentioned);
375
+ if (!mentioned) {
376
+ Wprint(tr("SATISFY: expression has no reference to trigdate() or $T..."));
377
+ }
378
+ }
379
+
380
+
381
+ static int
382
+ ComputeTrigDuration(TimeTrig const *t)
383
+ {
384
+ if (t->ttime == NO_TIME ||
385
+ t->duration == NO_TIME) {
386
+ return 0;
387
+ }
388
+ return (t->ttime + t->duration - 1) / MINUTES_PER_DAY;
389
+ }
390
+
391
+ /***************************************************************/
392
+ /* */
393
+ /* DoRem */
394
+ /* */
395
+ /* Do the REM command. */
396
+ /* */
397
+ /***************************************************************/
398
+ int DoRem(ParsePtr p)
399
+ {
400
+
401
+ Trigger trig;
402
+ TimeTrig tim;
403
+ int r, err;
404
+ int dse;
405
+ DynamicBuffer buf;
406
+ Token tok;
407
+
408
+ DBufInit(&buf);
409
+
410
+ /* Parse the trigger date and time */
411
+ if ( (r=ParseRem(p, &trig, &tim)) != OK ) {
412
+ FreeTrig(&trig);
413
+ return r;
414
+ }
415
+
416
+ if (trig.tz != NULL && tim.ttime == NO_TIME) {
417
+ PurgeEchoLine("%s\n", CurLine);
418
+ FreeTrig(&trig);
419
+ return E_TZ_NO_AT;
420
+ }
421
+
422
+ /* An empty string for time zone is just a missing time zone */
423
+ if (trig.tz != NULL && !*trig.tz) {
424
+ free( (void *) trig.tz);
425
+ trig.tz = NULL;
426
+ }
427
+
428
+ if (trig.complete_through != NO_DATE && !trig.is_todo) {
429
+ PurgeEchoLine("%s\n", CurLine);
430
+ FreeTrig(&trig);
431
+ return E_COMPLETE_WITHOUT_TODO;
432
+ }
433
+
434
+ if (trig.max_overdue >= 0 && !trig.is_todo) {
435
+ PurgeEchoLine("%s\n", CurLine);
436
+ FreeTrig(&trig);
437
+ return E_MAX_OVERDUE_WITHOUT_TODO;
438
+ }
439
+
440
+ if (trig.typ == NO_TYPE) {
441
+ if (!Hush) {
442
+ PurgeEchoLine("%s\n", "#!P! Cannot parse next line");
443
+ }
444
+ PurgeEchoLine("%s\n", CurLine);
445
+ FreeTrig(&trig);
446
+ return E_EOLN;
447
+ }
448
+ if (trig.typ == SAT_TYPE) {
449
+ if (!Hush) {
450
+ PurgeEchoLine("%s\n", "#!P: Cannot purge SATISFY-type reminders");
451
+ }
452
+ PurgeEchoLine("%s\n", CurLine);
453
+ EnterTimezone(trig.tz);
454
+ r=DoSatRemind(&trig, &tim, p);
455
+ ExitTimezone(trig.tz);
456
+ if (r) {
457
+ if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
458
+ r = OK;
459
+ }
460
+ FreeTrig(&trig);
461
+ if (r == E_EXPIRED) return OK;
462
+ return r;
463
+ }
464
+ if (!LastTrigValid) {
465
+ FreeTrig(&trig);
466
+ return OK;
467
+ }
468
+ r=ParseToken(p, &buf);
469
+ if (r) {
470
+ FreeTrig(&trig);
471
+ return r;
472
+ }
473
+ FindToken(DBufValue(&buf), &tok);
474
+ DBufFree(&buf);
475
+ if (tok.type == T_Empty || tok.type == T_Comment) {
476
+ r = OK;
477
+ if (trig.addomit) {
478
+ r = AddGlobalOmit(LastTriggerDate);
479
+ }
480
+ DBufFree(&buf);
481
+ FreeTrig(&trig);
482
+ return r;
483
+ }
484
+ if (tok.type != T_RemType || tok.val == SAT_TYPE) {
485
+ DBufFree(&buf);
486
+ FreeTrig(&trig);
487
+ return E_PARSE_ERR;
488
+ }
489
+ if (tok.val == PASSTHRU_TYPE) {
490
+ r=ParseToken(p, &buf);
491
+ if (r) {
492
+ FreeTrig(&trig);
493
+ return r;
494
+ }
495
+ if (!DBufLen(&buf)) {
496
+ FreeTrig(&trig);
497
+ DBufFree(&buf);
498
+ return E_EOLN;
499
+ }
500
+ StrnCpy(trig.passthru, DBufValue(&buf), PASSTHRU_LEN);
501
+ DBufFree(&buf);
502
+ }
503
+ trig.typ = tok.val;
504
+
505
+ /* Convert some SPECIALs back to plain types */
506
+ FixSpecialType(&trig);
507
+
508
+ dse = LastTriggerDate;
509
+ if (!LastTrigValid || PurgeMode) {
510
+ FreeTrig(&trig);
511
+ return OK;
512
+ }
513
+ } else {
514
+ /* Calculate the trigger date */
515
+ EnterTimezone(trig.tz);
516
+ dse = ComputeTrigger(get_scanfrom(&trig), &trig, &tim, &r, 1);
517
+ ExitTimezone(trig.tz);
518
+ if (r) {
519
+ if (PurgeMode) {
520
+ if (!Hush) {
521
+ PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", GetErr(r));
522
+ }
523
+ PurgeEchoLine("%s\n", CurLine);
524
+ }
525
+ if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
526
+ r = OK;
527
+ }
528
+ FreeTrig(&trig);
529
+ return r;
530
+ }
531
+ }
532
+
533
+ /* Adjust trigger date/time to time zone */
534
+ dse = AdjustTriggerForTimeZone(&trig, dse, &tim, 1);
535
+
536
+ /* Add to global OMITs if so indicated */
537
+ if (trig.addomit) {
538
+ r = AddGlobalOmit(dse);
539
+ if (r) {
540
+ FreeTrig(&trig);
541
+ return r;
542
+ }
543
+ }
544
+ if (PurgeMode) {
545
+ if (trig.expired || (!trig.is_todo && dse < DSEToday)) {
546
+ if (trig.expr_happened) {
547
+ if (trig.nonconst_expr) {
548
+ if (!Hush) {
549
+ PurgeEchoLine("%s\n", "#!P: Next line may have expired, but contains non-constant expression");
550
+ PurgeEchoLine("%s\n", "#!P: or a relative SCANFROM clause");
551
+ }
552
+ PurgeEchoLine("%s\n", CurLine);
553
+ } else {
554
+ if (!Hush) {
555
+ PurgeEchoLine("%s\n", "#!P: Next line has expired, but contains expression... please verify");
556
+ }
557
+ PurgeEchoLine("#!P: Expired: %s\n", CurLine);
558
+ }
559
+ } else {
560
+ PurgeEchoLine("#!P: Expired: %s\n", CurLine);
561
+ }
562
+ } else {
563
+ PurgeEchoLine("%s\n", CurLine);
564
+ }
565
+ FreeTrig(&trig);
566
+ return OK;
567
+ }
568
+
569
+ /* Queue the reminder, if necessary */
570
+ if (ShouldQueueReminder(&trig, &tim, dse)) {
571
+ QueueReminder(p, &trig, &tim, trig.sched, dse);
572
+ }
573
+ /* If we're in daemon mode, do nothing over here */
574
+ if (Daemon) {
575
+ FreeTrig(&trig);
576
+ return OK;
577
+ }
578
+
579
+ r = OK;
580
+
581
+ if (ShouldTriggerReminder(&trig, &tim, dse, &err)) {
582
+ /* Filter unwanted events/todos */
583
+ if (todo_filtered(&trig)) {
584
+ FreeTrig(&trig);
585
+ return OK;
586
+ }
587
+
588
+ if (JSONMode) {
589
+ DynamicBuffer body;
590
+ int y, m, d;
591
+ int if_depth = get_if_pointer() - get_base_if_pointer();
592
+ DBufInit(&body);
593
+ int red=-1, green=-1, blue=-1;
594
+ r=TriggerReminder(p, &trig, &tim, dse, 0, &body, &red, &green, &blue);
595
+ if (r) {
596
+ FreeTrig(&trig);
597
+ return r;
598
+ }
599
+ /* Remove trailing newlines from body */
600
+ remove_trailing_newlines(&body);
601
+
602
+ if (!*DBufValue(&body)) {
603
+ FreeTrig(&trig);
604
+ return r;
605
+ }
606
+ if (JSONLinesEmitted) {
607
+ printf("},\n");
608
+ }
609
+ JSONLinesEmitted++;
610
+ FromDSE(dse, &y, &m, &d);
611
+ printf("{\"date\":\"%04d-%02d-%02d\",", y, m+1, d);
612
+ PrintJSONKeyPairString("filename", GetCurrentFilename());
613
+ PrintJSONKeyPairInt("lineno", LineNo);
614
+ if (LineNoStart != LineNo) {
615
+ PrintJSONKeyPairInt("lineno_start", LineNoStart);
616
+ }
617
+ PrintJSONKeyPairString("passthru", trig.passthru);
618
+ if (trig.duration_days) {
619
+ PrintJSONKeyPairInt("duration", trig.duration_days);
620
+ }
621
+ if (tim.ttime != NO_TIME) {
622
+ PrintJSONKeyPairInt("time", tim.ttime);
623
+ if (tim.ttime_orig != tim.ttime) {
624
+ PrintJSONKeyPairInt("time_in_tz", tim.ttime_orig);
625
+ }
626
+ }
627
+ if (trig.nonconst_expr) {
628
+ PrintJSONKeyPairInt("nonconst_expr", 1);
629
+ }
630
+ if (if_depth) {
631
+ PrintJSONKeyPairInt("if_depth", if_depth);
632
+ }
633
+ if (tim.delta) {
634
+ PrintJSONKeyPairInt("tdelta", tim.delta);
635
+ }
636
+ if (tim.rep) {
637
+ PrintJSONKeyPairInt("trep", tim.rep);
638
+ }
639
+ if (red >= 0 && red <= 255 && green >= 0 && green <= 255 && blue >=0 && blue <= 255) {
640
+ PrintJSONKeyPairInt("r", red);
641
+ PrintJSONKeyPairInt("g", green);
642
+ PrintJSONKeyPairInt("b", blue);
643
+ }
644
+
645
+ WriteJSONTrigger(&trig, 1);
646
+ printf("\"body\":\"");
647
+ PrintJSONString(DBufValue(&body));
648
+ printf("\"");
649
+ } else {
650
+ r=TriggerReminder(p, &trig, &tim, dse, 0, NULL, NULL, NULL, NULL);
651
+ FreeTrig(&trig);
652
+ return r;
653
+ }
654
+ } else {
655
+ /* Parse the rest of the line to catch any potential
656
+ expression-pasting errors */
657
+ if (ParseUntriggered) {
658
+ while (ParseChar(p, &r, 0)) {
659
+ if (r != 0) {
660
+ break;
661
+ }
662
+ }
663
+ }
664
+ }
665
+
666
+ FreeTrig(&trig);
667
+ return r;
668
+ }
669
+
670
+ /***************************************************************/
671
+ /* */
672
+ /* GetFullDate - get a full date, either YYYY-MM-DD or */
673
+ /* YEAR MON DAY */
674
+ /* */
675
+ /* Returns OK on success or an error code on failure. Sets */
676
+ /* *dse on success. */
677
+ /* */
678
+ /***************************************************************/
679
+ static int GetFullDate(ParsePtr s, char const *prefix, int *dse)
680
+ {
681
+ Token tok;
682
+ DynamicBuffer buf;
683
+ int y = NO_YR, m = NO_MON, d = NO_DAY;
684
+ int r;
685
+ *dse = NO_DATE;
686
+
687
+ DBufInit(&buf);
688
+
689
+ while(1) {
690
+ r = ParseToken(s, &buf);
691
+ if (r) return r;
692
+ FindToken(DBufValue(&buf), &tok);
693
+ switch(tok.type) {
694
+ case T_Year:
695
+ DBufFree(&buf);
696
+ if (y != NO_YR) {
697
+ Eprint("%s: %s", prefix, GetErr(E_YR_TWICE));
698
+ return E_YR_TWICE;
699
+ }
700
+ y = tok.val;
701
+ break;
702
+
703
+ case T_Month:
704
+ DBufFree(&buf);
705
+ if (m != NO_MON) {
706
+ Eprint("%s: %s", prefix, GetErr(E_MON_TWICE));
707
+ return E_MON_TWICE;
708
+ }
709
+ m = tok.val;
710
+ break;
711
+
712
+ case T_Day:
713
+ DBufFree(&buf);
714
+ if (d != NO_DAY) {
715
+ Eprint("%s: %s", prefix, GetErr(E_DAY_TWICE));
716
+ return E_DAY_TWICE;
717
+ }
718
+ d = tok.val;
719
+ break;
720
+
721
+ case T_Date:
722
+ DBufFree(&buf);
723
+ if (y != NO_YR) {
724
+ Eprint("%s: %s", prefix, GetErr(E_YR_TWICE));
725
+ return E_YR_TWICE;
726
+ }
727
+ if (m != NO_MON) {
728
+ Eprint("%s: %s", prefix, GetErr(E_MON_TWICE));
729
+ return E_MON_TWICE;
730
+ }
731
+ if (d != NO_DAY) {
732
+ Eprint("%s: %s", prefix, GetErr(E_DAY_TWICE));
733
+ return E_DAY_TWICE;
734
+ }
735
+ if (*dse != NO_DATE) {
736
+ return E_DAY_TWICE;
737
+ }
738
+ *dse = tok.val;
739
+ /* We're done here! */
740
+ return OK;
741
+
742
+ default:
743
+ if (tok.type == T_Illegal && tok.val < 0) {
744
+ Eprint("%s: `%s'", GetErr(-tok.val), DBufValue(&buf));
745
+ DBufFree(&buf);
746
+ return -tok.val;
747
+ }
748
+ if (*dse == NO_DATE && (y == NO_YR || m == NO_MON || d == NO_DAY)) {
749
+ Eprint("%s: %s", prefix, GetErr(E_INCOMPLETE));
750
+ DBufFree(&buf);
751
+ return E_INCOMPLETE;
752
+ }
753
+ if (*dse != NO_DATE) {
754
+ PushToken(DBufValue(&buf), s);
755
+ DBufFree(&buf);
756
+ return OK;
757
+ }
758
+ if (!DateOK(y, m, d)) {
759
+ DBufFree(&buf);
760
+ return E_BAD_DATE;
761
+ }
762
+ *dse = DSE(y, m, d);
763
+ PushToken(DBufValue(&buf), s);
764
+ DBufFree(&buf);
765
+ return OK;
766
+ }
767
+ }
768
+ }
769
+
770
+ /***************************************************************/
771
+ /* */
772
+ /* ParseRem */
773
+ /* */
774
+ /* Given a parse pointer, parse line and fill in a */
775
+ /* trigger structure. */
776
+ /* */
777
+ /***************************************************************/
778
+ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
779
+ {
780
+ register int r;
781
+ DynamicBuffer buf;
782
+ Token tok;
783
+ int y, m, d;
784
+ int dse;
785
+ int seen_delta = 0;
786
+
787
+ DBufInit(&buf);
788
+
789
+ trig->y = NO_YR;
790
+ trig->m = NO_MON;
791
+ trig->d = NO_DAY;
792
+ trig->wd = NO_WD;
793
+ trig->back = NO_BACK;
794
+ trig->delta = -DefaultDelta;
795
+ trig->until = NO_UNTIL;
796
+ trig->rep = NO_REP;
797
+ trig->localomit = NO_WD;
798
+ trig->skip = NO_SKIP;
799
+ trig->once = NO_ONCE;
800
+ trig->addomit = 0;
801
+ trig->noqueue = 0;
802
+ trig->typ = NO_TYPE;
803
+ trig->scanfrom = NO_SCANFROM;
804
+ trig->from = NO_DATE;
805
+ trig->priority = DefaultPrio;
806
+ trig->sched[0] = 0;
807
+ trig->warn[0] = 0;
808
+ trig->omitfunc[0] = 0;
809
+ trig->duration_days = 0;
810
+ trig->eventstart = NO_DATETIME;
811
+ trig->eventstart_orig = NO_DATETIME;
812
+ trig->eventduration = NO_TIME;
813
+ trig->maybe_uncomputable = 0;
814
+ DBufInit(&(trig->tags));
815
+ trig->passthru[0] = 0;
816
+ tim->ttime = NO_TIME;
817
+ tim->ttime_orig = NO_TIME;
818
+ tim->delta = DefaultTDelta;
819
+ tim->rep = NO_REP;
820
+ tim->duration = NO_TIME;
821
+ trig->need_wkday = 0;
822
+ trig->is_todo = 0;
823
+ trig->max_overdue = -1;
824
+ trig->complete_through = NO_DATE;
825
+ trig->adj_for_last = 0;
826
+ trig->infos = NULL;
827
+ trig->tz = NULL;
828
+ trig->nonconst_expr = 0;
829
+ trig->expr_happened = 0;
830
+
831
+ int parsing = 1;
832
+ while(parsing) {
833
+ /* Read space-delimited string */
834
+ r = ParseToken(s, &buf);
835
+ if (r) return r;
836
+
837
+ /* Figure out what we've got */
838
+ FindToken(DBufValue(&buf), &tok);
839
+ switch(tok.type) {
840
+ case T_Todo:
841
+ if (trig->is_todo) return E_TODO_TWICE;
842
+ trig->is_todo = 1;
843
+ break;
844
+
845
+ case T_In:
846
+ /* Completely ignored */
847
+ DBufFree(&buf);
848
+ break;
849
+
850
+ case T_Ordinal:
851
+ DBufFree(&buf);
852
+ if (trig->d != NO_DAY) return E_DAY_TWICE;
853
+ if (tok.val < 0) {
854
+ if (trig->back != NO_BACK) return E_BACK_TWICE;
855
+ trig->back = -7;
856
+ trig->d = 1;
857
+ trig->adj_for_last = 1;
858
+ } else {
859
+ trig->d = 1 + 7 * tok.val;
860
+ }
861
+ trig->need_wkday = 1;
862
+ break;
863
+
864
+ case T_Date:
865
+ DBufFree(&buf);
866
+ if (trig->d != NO_DAY) {
867
+ return E_DAY_TWICE;
868
+ }
869
+ if (trig->m != NO_MON) {
870
+ return E_MON_TWICE;
871
+ }
872
+ if (trig->y != NO_YR) {
873
+ return E_YR_TWICE;
874
+ }
875
+
876
+ FromDSE(tok.val, &y, &m, &d);
877
+ trig->y = y;
878
+ trig->m = m;
879
+ trig->d = d;
880
+ break;
881
+
882
+ case T_DateTime:
883
+ DBufFree(&buf);
884
+ if (trig->d != NO_DAY) return E_DAY_TWICE;
885
+ if (trig->m != NO_MON) return E_MON_TWICE;
886
+ if (trig->y != NO_YR) return E_YR_TWICE;
887
+ FromDSE(tok.val / MINUTES_PER_DAY, &y, &m, &d);
888
+ trig->y = y;
889
+ trig->m = m;
890
+ trig->d = d;
891
+ tim->ttime = (tok.val % MINUTES_PER_DAY);
892
+ tim->ttime_orig = tim->ttime;
893
+ break;
894
+
895
+ case T_WkDay:
896
+ DBufFree(&buf);
897
+ if (trig->wd & (1 << tok.val)) return E_WD_TWICE;
898
+ trig->wd |= (1 << tok.val);
899
+ break;
900
+
901
+ case T_Month:
902
+ DBufFree(&buf);
903
+ if (trig->m != NO_MON) return E_MON_TWICE;
904
+ trig->m = tok.val;
905
+ break;
906
+
907
+ case T_MaybeUncomputable:
908
+ DBufFree(&buf);
909
+ trig->maybe_uncomputable = 1;
910
+ break;
911
+
912
+ case T_Skip:
913
+ DBufFree(&buf);
914
+ if (trig->skip != NO_SKIP) return E_SKIP_ERR;
915
+ trig->skip = tok.val;
916
+ break;
917
+
918
+ case T_MaxOverdue:
919
+ if (trig->max_overdue >= 0) return E_MAX_OVERDUE_TWICE;
920
+ DBufFree(&buf);
921
+ r = ParseToken(s, &buf);
922
+ if (r) return r;
923
+ FindToken(DBufValue(&buf), &tok);
924
+ DBufFree(&buf);
925
+ if (tok.type == T_Illegal) {
926
+ return -tok.val;
927
+ }
928
+ if (tok.type != T_Day && tok.type != T_Year && tok.type != T_Number) {
929
+ return E_EXPECTING_NUMBER;
930
+ }
931
+ if (tok.val < 0) {
932
+ return E_2LOW;
933
+ }
934
+ trig->max_overdue = tok.val;
935
+ break;
936
+
937
+ case T_Priority:
938
+ DBufFree(&buf);
939
+ r=ParsePriority(s, trig);
940
+ if (r) return r;
941
+ break;
942
+
943
+ /* A time implicitly introduces an AT if AT is not explicit */
944
+ case T_Time:
945
+ DBufFree(&buf);
946
+ if (tim->ttime != NO_TIME) return E_TIME_TWICE;
947
+ tim->ttime = tok.val;
948
+ tim->ttime_orig = tok.val;
949
+ r = ParseTimeTrig(s, tim);
950
+ if (r) return r;
951
+ trig->duration_days = ComputeTrigDuration(tim);
952
+ break;
953
+
954
+ case T_At:
955
+ DBufFree(&buf);
956
+ r=ParseTimeTrig(s, tim);
957
+ if (r) return r;
958
+ trig->duration_days = ComputeTrigDuration(tim);
959
+ break;
960
+
961
+ case T_Scanfrom:
962
+ DBufFree(&buf);
963
+ r=ParseScanFrom(s, trig, tok.val);
964
+ if (r) return r;
965
+ break;
966
+
967
+ case T_RemType:
968
+ DBufFree(&buf);
969
+ trig->typ = tok.val;
970
+ if (s->isnested) return E_CANT_NEST_RTYPE;
971
+ if (trig->typ == PASSTHRU_TYPE) {
972
+ r = ParseToken(s, &buf);
973
+ if (r) return r;
974
+ if (!DBufLen(&buf)) {
975
+ DBufFree(&buf);
976
+ return E_EOLN;
977
+ }
978
+ StrnCpy(trig->passthru, DBufValue(&buf), PASSTHRU_LEN);
979
+ }
980
+ FixSpecialType(trig);
981
+ parsing = 0;
982
+ break;
983
+
984
+ case T_Through:
985
+ DBufFree(&buf);
986
+ if (trig->rep != NO_REP) return E_REP_TWICE;
987
+ trig->rep = 1;
988
+ r = ParseUntil(s, trig, tok.type);
989
+ if (r) return r;
990
+ break;
991
+
992
+ case T_CompleteThrough:
993
+ if (trig->complete_through != NO_DATE) return E_COMPLETE_THROUGH_TWICE;
994
+ r = GetFullDate(s, "COMPLETE-THROUGH", &dse);
995
+ if (r != OK) return r;
996
+ trig->complete_through = dse;
997
+ break;
998
+
999
+ case T_Until:
1000
+ DBufFree(&buf);
1001
+ r=ParseUntil(s, trig, tok.type);
1002
+ if (r) return r;
1003
+ break;
1004
+
1005
+ case T_Number:
1006
+ DBufFree(&buf);
1007
+ Eprint("`%d' is not recognized as a year (%d-%d) or a day number (1-31)",
1008
+ tok.val, BASE, BASE+YR_RANGE);
1009
+ return E_PARSE_ERR;
1010
+
1011
+ case T_Year:
1012
+ DBufFree(&buf);
1013
+ if (trig->y != NO_YR) return E_YR_TWICE;
1014
+ trig->y = tok.val;
1015
+ break;
1016
+
1017
+ case T_Day:
1018
+ DBufFree(&buf);
1019
+ if (trig->d != NO_DAY) return E_DAY_TWICE;
1020
+ trig->d = tok.val;
1021
+ break;
1022
+
1023
+ case T_Rep:
1024
+ DBufFree(&buf);
1025
+ if (trig->rep != NO_REP) return E_REP_TWICE;
1026
+ trig->rep = tok.val;
1027
+ break;
1028
+
1029
+ case T_Delta:
1030
+ DBufFree(&buf);
1031
+ if (seen_delta) return E_DELTA_TWICE;
1032
+ seen_delta = 1;
1033
+ trig->delta = tok.val;
1034
+ break;
1035
+
1036
+ case T_Back:
1037
+ DBufFree(&buf);
1038
+ if (trig->back != NO_BACK) return E_BACK_TWICE;
1039
+ trig->back = tok.val;
1040
+ break;
1041
+
1042
+ case T_BackAdj:
1043
+ DBufFree(&buf);
1044
+ if (trig->back != NO_BACK) return E_BACK_TWICE;
1045
+ if (trig->d != NO_DAY) return E_DAY_TWICE;
1046
+ trig->back = tok.val;
1047
+ trig->d = 1;
1048
+ trig->adj_for_last = 1;
1049
+ break;
1050
+
1051
+ case T_Once:
1052
+ DBufFree(&buf);
1053
+ if (trig->once != NO_ONCE) return E_ONCE_TWICE;
1054
+ trig->once = ONCE_ONCE;
1055
+ break;
1056
+
1057
+ case T_AddOmit:
1058
+ DBufFree(&buf);
1059
+ trig->addomit = 1;
1060
+ break;
1061
+
1062
+ case T_NoQueue:
1063
+ DBufFree(&buf);
1064
+ trig->noqueue = 1;
1065
+ break;
1066
+
1067
+ case T_Omit:
1068
+ DBufFree(&buf);
1069
+ if (trig->omitfunc[0]) {
1070
+ Wprint(tr("Warning: OMIT is ignored if you use OMITFUNC"));
1071
+ }
1072
+
1073
+ r = ParseLocalOmit(s, trig);
1074
+ if (r) return r;
1075
+ break;
1076
+
1077
+ case T_Empty:
1078
+ DBufFree(&buf);
1079
+ parsing = 0;
1080
+ break;
1081
+
1082
+ case T_OmitFunc:
1083
+ if (trig->localomit) {
1084
+ Wprint(tr("Warning: OMIT is ignored if you use OMITFUNC"));
1085
+ }
1086
+ r=ParseToken(s, &buf);
1087
+ if (r) return r;
1088
+ StrnCpy(trig->omitfunc, DBufValue(&buf), VAR_NAME_LEN);
1089
+ strtolower(trig->omitfunc);
1090
+ /* An OMITFUNC counts as a nonconst_expr! */
1091
+ s->expr_happened = 1;
1092
+ nonconst_debug(s->nonconst_expr, tr("OMITFUNC counts as a non-constant expression"));
1093
+ s->nonconst_expr = 1;
1094
+ trig->nonconst_expr = 1;
1095
+ DBufFree(&buf);
1096
+ break;
1097
+
1098
+ case T_Warn:
1099
+ r=ParseToken(s, &buf);
1100
+ if(r) return r;
1101
+ StrnCpy(trig->warn, DBufValue(&buf), VAR_NAME_LEN);
1102
+ strtolower(trig->warn);
1103
+ DBufFree(&buf);
1104
+ break;
1105
+
1106
+ case T_Tz:
1107
+ if (trig->tz) {
1108
+ return E_TZ_SPECIFIED_TWICE;
1109
+ }
1110
+
1111
+ r = ParseTokenOrQuotedString(s, &buf);
1112
+ if (r != OK) {
1113
+ return r;
1114
+ }
1115
+ trig->tz = strdup(DBufValue(&buf));
1116
+ if (!trig->tz) {
1117
+ return E_NO_MEM;
1118
+ }
1119
+ DBufFree(&buf);
1120
+ break;
1121
+
1122
+ case T_Info:
1123
+ r = ParseQuotedString(s, &buf);
1124
+ if (r != OK) {
1125
+ return r;
1126
+ }
1127
+ r = AppendTrigInfo(trig, DBufValue(&buf));
1128
+ DBufFree(&buf);
1129
+ if (r) return r;
1130
+ break;
1131
+ case T_Tag:
1132
+ r = ParseToken(s, &buf);
1133
+ if (r) return r;
1134
+ if (strchr(DBufValue(&buf), ',')) {
1135
+ DBufFree(&buf);
1136
+ return E_PARSE_ERR;
1137
+ }
1138
+ AppendTag(&(trig->tags), DBufValue(&buf));
1139
+ DBufFree(&buf);
1140
+ break;
1141
+
1142
+ case T_Duration:
1143
+ r = ParseToken(s, &buf);
1144
+ if (r) return r;
1145
+ FindToken(DBufValue(&buf), &tok);
1146
+ DBufFree(&buf);
1147
+ switch(tok.type) {
1148
+ case T_Time:
1149
+ case T_LongTime:
1150
+ case T_Year:
1151
+ case T_Day:
1152
+ case T_Number:
1153
+ if (tok.val != 0) {
1154
+ tim->duration = tok.val;
1155
+ } else {
1156
+ tim->duration = NO_TIME;
1157
+ }
1158
+ trig->duration_days = ComputeTrigDuration(tim);
1159
+ break;
1160
+ default:
1161
+ return E_BAD_TIME;
1162
+ }
1163
+ break;
1164
+
1165
+ case T_Sched:
1166
+ r=ParseToken(s, &buf);
1167
+ if(r) return r;
1168
+ StrnCpy(trig->sched, DBufValue(&buf), VAR_NAME_LEN);
1169
+ strtolower(trig->sched);
1170
+ DBufFree(&buf);
1171
+ break;
1172
+
1173
+ case T_LongTime:
1174
+ DBufFree(&buf);
1175
+ return E_BAD_TIME;
1176
+ break;
1177
+
1178
+ default:
1179
+ if (tok.type == T_Illegal && tok.val < 0) {
1180
+ Eprint("%s: `%s'", GetErr(-tok.val), DBufValue(&buf));
1181
+ DBufFree(&buf);
1182
+ return -tok.val;
1183
+ }
1184
+ PushToken(DBufValue(&buf), s);
1185
+ DBufFree(&buf);
1186
+ trig->typ = MSG_TYPE;
1187
+ if (s->isnested) return E_CANT_NEST_RTYPE;
1188
+ if (!WarnedAboutImplicit && !SuppressImplicitRemWarnings) {
1189
+ if (warning_level("05.00.03")) {
1190
+ Wprint(tr("Missing REM type; assuming MSG"));
1191
+ }
1192
+ WarnedAboutImplicit = 1;
1193
+ }
1194
+ parsing = 0;
1195
+ break;
1196
+ }
1197
+ }
1198
+
1199
+ if (s->nonconst_expr) {
1200
+ trig->nonconst_expr = 1;
1201
+ }
1202
+ if (s->expr_happened) {
1203
+ trig->expr_happened = 1;
1204
+ }
1205
+ if (trig->need_wkday && trig->wd == NO_WD) {
1206
+ Eprint("Weekday name(s) required");
1207
+ return E_PARSE_ERR;
1208
+ }
1209
+
1210
+ /* Adjust month and possibly year */
1211
+ if (trig->adj_for_last) {
1212
+ if (trig->m != NO_MON) {
1213
+ trig->m++;
1214
+ if (trig->m >= 12) {
1215
+ trig->m = 0;
1216
+ if (trig->y != NO_YR) {
1217
+ trig->y++;
1218
+ }
1219
+ }
1220
+ }
1221
+ trig->adj_for_last = 0;
1222
+ }
1223
+
1224
+ /* Check for some warning conditions */
1225
+ if (warning_level("06.01.03")) {
1226
+ if (trig->addomit) {
1227
+ if (trig->y == NO_YR || trig->m == NO_MON || trig->d == NO_DAY || trig->rep != NO_REP) {
1228
+ if (trig->scanfrom == NO_SCANFROM) {
1229
+ if (trig->y == NO_YR && trig->m != NO_MON && trig->d != NO_DAY) {
1230
+ Wprint(tr("Warning: Consider using SCANFROM -28 with recurring ADDOMIT"));
1231
+ } else if (trig->m == NO_MON && trig->d != NO_DAY) {
1232
+ Wprint(tr("Warning: Consider using SCANFROM -7 with recurring ADDOMIT"));
1233
+ } else {
1234
+ Wprint(tr("Warning: Consider using SCANFROM with recurring ADDOMIT"));
1235
+ }
1236
+ }
1237
+ }
1238
+ }
1239
+ }
1240
+
1241
+ if (!trig->nonconst_expr) {
1242
+ if (trig->y != NO_YR && trig->m != NO_MON && trig->d != NO_DAY && trig->until != NO_UNTIL) {
1243
+ if (DSE(trig->y, trig->m, trig->d) > trig->until) {
1244
+ Wprint(tr("Warning: UNTIL/THROUGH date earlier than start date"));
1245
+ }
1246
+ }
1247
+ if (trig->from != NO_DATE) {
1248
+ if (trig->until != NO_UNTIL && trig->until < trig->from) {
1249
+ Wprint(tr("Warning: UNTIL/THROUGH date earlier than FROM date"));
1250
+ }
1251
+ } else if (get_raw_scanfrom(trig) != NO_SCANFROM) {
1252
+ if (trig->until != NO_UNTIL && trig->until < get_raw_scanfrom(trig)) {
1253
+ Wprint(tr("Warning: UNTIL/THROUGH date earlier than SCANFROM date"));
1254
+ }
1255
+ }
1256
+ }
1257
+
1258
+ if (trig->y != NO_YR && trig->m != NO_MON && trig->d != NO_DAY && trig->until != NO_UNTIL && trig->rep == NO_REP) {
1259
+ Wprint(tr("Warning: Useless use of UNTIL with fully-specified date and no *rep"));
1260
+ }
1261
+
1262
+ /* Check that any SCHED / WARN / OMITFUNC functions refer to
1263
+ their arguments */
1264
+ if (warning_level("05.00.03")) {
1265
+ check_trigger_function(trig->sched, "SCHED");
1266
+ check_trigger_function(trig->warn, "WARN");
1267
+ check_trigger_function(trig->omitfunc, "OMITFUNC");
1268
+ }
1269
+
1270
+ /* If we have a SCHED, ignore any time delta */
1271
+ if (trig->sched[0]) {
1272
+ tim->delta = NO_DELTA;
1273
+ }
1274
+
1275
+ /* Check that TZ looks plausible */
1276
+ if (trig->tz && (*trig->tz != '!')) {
1277
+ warn_if_timezone_bad(trig->tz);
1278
+ }
1279
+
1280
+ /* Remove leading ! from TZ spec */
1281
+ if (trig->tz && *trig->tz == '!') {
1282
+ char *stz = (char *) trig->tz;
1283
+ while (*stz) {
1284
+ *stz = *(stz+1);
1285
+ stz++;
1286
+ }
1287
+ }
1288
+ return OK;
1289
+ }
1290
+
1291
+ /***************************************************************/
1292
+ /* */
1293
+ /* ParseTimeTrig - parse the AT part of a timed reminder */
1294
+ /* */
1295
+ /***************************************************************/
1296
+ static int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
1297
+ {
1298
+ Token tok;
1299
+ int r;
1300
+ int seen_delta = 0;
1301
+ DynamicBuffer buf;
1302
+ DBufInit(&buf);
1303
+
1304
+ while(1) {
1305
+ r = ParseToken(s, &buf);
1306
+ if (r) return r;
1307
+ FindToken(DBufValue(&buf), &tok);
1308
+ switch(tok.type) {
1309
+ case T_Time:
1310
+ DBufFree(&buf);
1311
+ if (tim->ttime != NO_TIME) return E_TIME_TWICE;
1312
+ tim->ttime = tok.val;
1313
+ tim->ttime_orig = tok.val;
1314
+ break;
1315
+
1316
+ case T_Delta:
1317
+ DBufFree(&buf);
1318
+ if (seen_delta) return E_DELTA_TWICE;
1319
+ seen_delta = 1;
1320
+ tim->delta = (tok.val >= 0) ? tok.val : -tok.val;
1321
+ break;
1322
+
1323
+ case T_Rep:
1324
+ DBufFree(&buf);
1325
+ if (tim->rep != NO_REP) return E_REP_TWICE;
1326
+ tim->rep = tok.val;
1327
+ break;
1328
+
1329
+ default:
1330
+ if (tok.type == T_Illegal && tok.val < 0) {
1331
+ Eprint("%s: `%s'", GetErr(-tok.val), DBufValue(&buf));
1332
+ DBufFree(&buf);
1333
+ return -tok.val;
1334
+ }
1335
+ if (tim->ttime == NO_TIME) return E_EXPECT_TIME;
1336
+
1337
+ PushToken(DBufValue(&buf), s);
1338
+ DBufFree(&buf);
1339
+ return OK;
1340
+ }
1341
+ }
1342
+ }
1343
+
1344
+ /***************************************************************/
1345
+ /* */
1346
+ /* ParseLocalOmit - parse the local OMIT portion of a */
1347
+ /* reminder. */
1348
+ /* */
1349
+ /***************************************************************/
1350
+ static int ParseLocalOmit(ParsePtr s, Trigger *t)
1351
+ {
1352
+ Token tok;
1353
+ int r;
1354
+ DynamicBuffer buf;
1355
+ DBufInit(&buf);
1356
+
1357
+ while(1) {
1358
+ r = ParseToken(s, &buf);
1359
+ if (r) return r;
1360
+ FindToken(DBufValue(&buf), &tok);
1361
+ switch(tok.type) {
1362
+ case T_WkDay:
1363
+ DBufFree(&buf);
1364
+ t->localomit |= (1 << tok.val);
1365
+ break;
1366
+
1367
+ default:
1368
+ if (t->localomit == NO_WD) {
1369
+ return E_EXPECTING_WEEKDAY;
1370
+ }
1371
+ PushToken(DBufValue(&buf), s);
1372
+ DBufFree(&buf);
1373
+ return OK;
1374
+ }
1375
+ }
1376
+ }
1377
+
1378
+ /***************************************************************/
1379
+ /* */
1380
+ /* ParseUntil - parse the UNTIL portion of a reminder */
1381
+ /* */
1382
+ /***************************************************************/
1383
+ static int ParseUntil(ParsePtr s, Trigger *t, int type)
1384
+ {
1385
+
1386
+ char const *which;
1387
+ int dse;
1388
+
1389
+ if (type == T_Until) {
1390
+ which = "UNTIL";
1391
+ } else {
1392
+ which = "THROUGH";
1393
+ }
1394
+
1395
+ if (t->until != NO_UNTIL) return E_UNTIL_TWICE;
1396
+
1397
+ int r = GetFullDate(s, which, &dse);
1398
+ if (r != OK) {
1399
+ return r;
1400
+ }
1401
+
1402
+ t->until = dse;
1403
+ return OK;
1404
+ }
1405
+
1406
+ /***************************************************************/
1407
+ /* */
1408
+ /* ParseScanFrom - parse the FROM/SCANFROM portion */
1409
+ /* */
1410
+ /***************************************************************/
1411
+ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
1412
+ {
1413
+ int r;
1414
+ int y = NO_YR, m = NO_MON, d = NO_DAY;
1415
+ Token tok;
1416
+ DynamicBuffer buf;
1417
+ char const *word;
1418
+
1419
+ DBufInit(&buf);
1420
+ if (type == SCANFROM_TYPE) {
1421
+ word = "SCANFROM";
1422
+ } else {
1423
+ word = "FROM";
1424
+ }
1425
+
1426
+ if (t->scanfrom != NO_SCANFROM) return E_SCAN_TWICE;
1427
+ if (t->from != NO_DATE) return E_SCAN_TWICE;
1428
+ while(1) {
1429
+ r = ParseToken(s, &buf);
1430
+ if (r) return r;
1431
+ FindToken(DBufValue(&buf), &tok);
1432
+ switch(tok.type) {
1433
+ case T_Year:
1434
+ DBufFree(&buf);
1435
+ if (y != NO_YR) {
1436
+ Eprint("%s: %s", word, GetErr(E_YR_TWICE));
1437
+ return E_YR_TWICE;
1438
+ }
1439
+ y = tok.val;
1440
+ break;
1441
+
1442
+ case T_Month:
1443
+ DBufFree(&buf);
1444
+ if (m != NO_MON) {
1445
+ Eprint("%s: %s", word, GetErr(E_MON_TWICE));
1446
+ return E_MON_TWICE;
1447
+ }
1448
+ m = tok.val;
1449
+ break;
1450
+
1451
+ case T_Day:
1452
+ DBufFree(&buf);
1453
+ if (d != NO_DAY) {
1454
+ Eprint("%s: %s", word, GetErr(E_DAY_TWICE));
1455
+ return E_DAY_TWICE;
1456
+ }
1457
+ d = tok.val;
1458
+ break;
1459
+
1460
+ case T_Date:
1461
+ DBufFree(&buf);
1462
+ if (y != NO_YR) {
1463
+ Eprint("%s: %s", word, GetErr(E_YR_TWICE));
1464
+ return E_YR_TWICE;
1465
+ }
1466
+ if (m != NO_MON) {
1467
+ Eprint("%s: %s", word, GetErr(E_MON_TWICE));
1468
+ return E_MON_TWICE;
1469
+ }
1470
+ if (d != NO_DAY) {
1471
+ Eprint("%s: %s", word, GetErr(E_DAY_TWICE));
1472
+ return E_DAY_TWICE;
1473
+ }
1474
+ if (type == FROM_TYPE) {
1475
+ t->from = tok.val;
1476
+ } else {
1477
+ t->scanfrom = tok.val;
1478
+ }
1479
+ return OK;
1480
+
1481
+ case T_Back:
1482
+ DBufFree(&buf);
1483
+ if (type != SCANFROM_TYPE) {
1484
+ Eprint("%s: %s", word, GetErr(E_INCOMPLETE));
1485
+ return E_INCOMPLETE;
1486
+ }
1487
+ if (y != NO_YR) {
1488
+ Eprint("%s: %s", word, GetErr(E_YR_TWICE));
1489
+ return E_YR_TWICE;
1490
+ }
1491
+ if (m != NO_MON) {
1492
+ Eprint("%s: %s", word, GetErr(E_MON_TWICE));
1493
+ return E_MON_TWICE;
1494
+ }
1495
+ if (d != NO_DAY) {
1496
+ Eprint("%s: %s", word, GetErr(E_DAY_TWICE));
1497
+ return E_DAY_TWICE;
1498
+ }
1499
+ if (tok.val > 0) {
1500
+ tok.val = -tok.val;
1501
+ }
1502
+ t->scanfrom = tok.val;
1503
+ s->expr_happened = 1;
1504
+ nonconst_debug(s->nonconst_expr, tr("Relative SCANFROM counts as a non-constant expression"));
1505
+ s->nonconst_expr = 1;
1506
+ t->nonconst_expr = 1;
1507
+ return OK;
1508
+
1509
+ default:
1510
+ if (tok.type == T_Illegal && tok.val < 0) {
1511
+ Eprint("%s: `%s'", GetErr(-tok.val), DBufValue(&buf));
1512
+ DBufFree(&buf);
1513
+ return -tok.val;
1514
+ }
1515
+ if (y == NO_YR || m == NO_MON || d == NO_DAY) {
1516
+ Eprint("%s: %s", word, GetErr(E_INCOMPLETE));
1517
+ DBufFree(&buf);
1518
+ return E_INCOMPLETE;
1519
+ }
1520
+ if (!DateOK(y, m, d)) {
1521
+ DBufFree(&buf);
1522
+ return E_BAD_DATE;
1523
+ }
1524
+ if (type == FROM_TYPE) {
1525
+ t->from = DSE(y, m, d);
1526
+ } else {
1527
+ t->scanfrom = DSE(y, m, d);
1528
+ }
1529
+
1530
+ PushToken(DBufValue(&buf), s);
1531
+ DBufFree(&buf);
1532
+ return OK;
1533
+ }
1534
+ }
1535
+ }
1536
+
1537
+
1538
+ /***************************************************************/
1539
+ /* */
1540
+ /* TriggerReminder */
1541
+ /* */
1542
+ /* Trigger the reminder if it's a RUN or MSG type. */
1543
+ /* */
1544
+ /***************************************************************/
1545
+ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig const *tim, int dse, int is_queued, DynamicBuffer *output, int *rr, int *gg, int *bb)
1546
+ {
1547
+ int r, y, m, d;
1548
+ int adjusted_for_newline = 0;
1549
+ char PrioExpr[VAR_NAME_LEN+25];
1550
+ char tmpBuf[64];
1551
+ DynamicBuffer buf, calRow;
1552
+ DynamicBuffer pre_buf;
1553
+ char const *s;
1554
+ char const *msg_command = NULL;
1555
+ char const *url;
1556
+ Value v;
1557
+
1558
+ if (MsgCommand) {
1559
+ msg_command = MsgCommand;
1560
+ }
1561
+ if (is_queued && QueuedMsgCommand) {
1562
+ msg_command = QueuedMsgCommand;
1563
+ }
1564
+
1565
+ /* A null command is no command */
1566
+ if (msg_command && !*msg_command) {
1567
+ msg_command = NULL;
1568
+ }
1569
+
1570
+ int red = -1, green = -1, blue = -1;
1571
+ int is_color = 0;
1572
+
1573
+ DBufInit(&buf);
1574
+ DBufInit(&calRow);
1575
+ DBufInit(&pre_buf);
1576
+ if (t->typ == RUN_TYPE && RunDisabled) return E_RUN_DISABLED;
1577
+ if ((t->typ == PASSTHRU_TYPE && strcasecmp(t->passthru, "COLOR") && strcasecmp(t->passthru, "COLOUR")) ||
1578
+ t->typ == CAL_TYPE ||
1579
+ t->typ == PS_TYPE ||
1580
+ t->typ == PSF_TYPE)
1581
+ return OK;
1582
+
1583
+ /* Handle COLOR types */
1584
+ if (t->typ == PASSTHRU_TYPE && (!strcasecmp(t->passthru, "COLOR") || !strcasecmp(t->passthru, "COLOUR"))) {
1585
+ /* Strip off three tokens */
1586
+ r = ParseToken(p, &buf);
1587
+ sscanf(DBufValue(&buf), "%d", &red);
1588
+ if (!NextMode) {
1589
+ DBufPuts(&pre_buf, DBufValue(&buf));
1590
+ DBufPutc(&pre_buf, ' ');
1591
+ }
1592
+ DBufFree(&buf);
1593
+ if (r) return r;
1594
+ r = ParseToken(p, &buf);
1595
+ sscanf(DBufValue(&buf), "%d", &green);
1596
+ if (!NextMode) {
1597
+ DBufPuts(&pre_buf, DBufValue(&buf));
1598
+ DBufPutc(&pre_buf, ' ');
1599
+ }
1600
+ DBufFree(&buf);
1601
+ if (r) return r;
1602
+ r = ParseToken(p, &buf);
1603
+ sscanf(DBufValue(&buf), "%d", &blue);
1604
+ if (!NextMode) {
1605
+ DBufPuts(&pre_buf, DBufValue(&buf));
1606
+ DBufPutc(&pre_buf, ' ');
1607
+ }
1608
+ DBufFree(&buf);
1609
+ if (r) return r;
1610
+ t->typ = MSG_TYPE;
1611
+
1612
+ if (red < 0 || green < 0 || blue < 0 || red > 255 || green > 255 || blue > 255) {
1613
+ red = -1;
1614
+ green = -1;
1615
+ blue = -1;
1616
+ t->passthru[0] = 0;
1617
+ }
1618
+ }
1619
+ /* If it's a MSG-type reminder, and no -k option was used, issue the banner. */
1620
+ if ((t->typ == MSG_TYPE || t->typ == MSF_TYPE)
1621
+ && !DidMsgReminder && !NextMode && !msg_command && !is_queued) {
1622
+ DynamicBuffer buf2;
1623
+ DBufInit(&buf2);
1624
+ DidMsgReminder = 1;
1625
+ if (!DoSubstFromString(DBufValue(&Banner), &buf2,
1626
+ DSEToday, NO_TIME) &&
1627
+ DBufLen(&buf2)) {
1628
+ if (!JSONMode) {
1629
+ printf("%s\n", DBufValue(&buf2));
1630
+ } else {
1631
+ if (JSONLinesEmitted) {
1632
+ printf("},\n");
1633
+ }
1634
+ JSONLinesEmitted++;
1635
+ printf("{\"banner\":\"");
1636
+ remove_trailing_newlines(&buf2);
1637
+ PrintJSONString(DBufValue(&buf2));
1638
+ printf("\"");
1639
+ }
1640
+ }
1641
+ DBufFree(&buf2);
1642
+ }
1643
+
1644
+ /* If it's NextMode, process as a ADVANCE_MODE-type entry, and issue
1645
+ simple-calendar format. */
1646
+ if (NextMode) {
1647
+ if ( (r=DoSubst(p, &buf, t, tim, dse, ADVANCE_MODE)) ) return r;
1648
+ if (!DBufLen(&buf)) {
1649
+ DBufFree(&buf);
1650
+ DBufFree(&pre_buf);
1651
+ return OK;
1652
+ }
1653
+ FromDSE(dse, &y, &m, &d);
1654
+ snprintf(tmpBuf, sizeof(tmpBuf), "%04d/%02d/%02d ", y, m+1, d);
1655
+ if (DBufPuts(&calRow, tmpBuf) != OK) {
1656
+ DBufFree(&calRow);
1657
+ DBufFree(&pre_buf);
1658
+ return E_NO_MEM;
1659
+ }
1660
+ /* If DoSimpleCalendar==1, output *all* simple calendar fields */
1661
+ if (DoSimpleCalendar) {
1662
+ /* ignore passthru field when in NextMode */
1663
+ if (DBufPuts(&calRow, "* ") != OK) {
1664
+ DBufFree(&calRow);
1665
+ DBufFree(&pre_buf);
1666
+ return E_NO_MEM;
1667
+ }
1668
+ if (*DBufValue(&(t->tags))) {
1669
+ DBufPuts(&calRow, DBufValue(&(t->tags)));
1670
+ DBufPutc(&calRow, ' ');
1671
+ } else {
1672
+ DBufPuts(&calRow, "* ");
1673
+ }
1674
+ if (tim->duration != NO_TIME) {
1675
+ snprintf(tmpBuf, sizeof(tmpBuf), "%d ", tim->duration);
1676
+ } else {
1677
+ snprintf(tmpBuf, sizeof(tmpBuf), "* ");
1678
+ }
1679
+ if (DBufPuts(&calRow, tmpBuf) != OK) {
1680
+ DBufFree(&calRow);
1681
+ DBufFree(&pre_buf);
1682
+ return E_NO_MEM;
1683
+ }
1684
+ if (tim->ttime != NO_TIME) {
1685
+ snprintf(tmpBuf, sizeof(tmpBuf), "%d ", tim->ttime);
1686
+ } else {
1687
+ snprintf(tmpBuf, sizeof(tmpBuf), "* ");
1688
+ }
1689
+ if (DBufPuts(&calRow, tmpBuf) != OK) {
1690
+ DBufFree(&calRow);
1691
+ DBufFree(&pre_buf);
1692
+ return E_NO_MEM;
1693
+ }
1694
+ }
1695
+ if (DBufPuts(&calRow, SimpleTime(tim->ttime)) != OK) {
1696
+ DBufFree(&calRow);
1697
+ DBufFree(&pre_buf);
1698
+ return E_NO_MEM;
1699
+ }
1700
+
1701
+ r = OK;
1702
+ if (output) {
1703
+ if (DBufPuts(output, DBufValue(&calRow)) != OK) r = E_NO_MEM;
1704
+ if (DBufPuts(output, DBufValue(&pre_buf)) != OK) r = E_NO_MEM;
1705
+ if (DBufPuts(output, DBufValue(&buf)) != OK) r = E_NO_MEM;
1706
+ } else {
1707
+ printf("%s%s%s\n", DBufValue(&calRow), DBufValue(&pre_buf), DBufValue(&buf));
1708
+ }
1709
+ DBufFree(&buf);
1710
+ DBufFree(&pre_buf);
1711
+ DBufFree(&calRow);
1712
+ return r;
1713
+ }
1714
+
1715
+ /* Correct colors */
1716
+ if (JSONMode || UseVTColors) {
1717
+ if (red == -1 && green == -1 && blue == -1) {
1718
+ if (DefaultColorR != -1 && DefaultColorG != -1 && DefaultColorB != -1) {
1719
+ red = DefaultColorR;
1720
+ green = DefaultColorG;
1721
+ blue = DefaultColorB;
1722
+ }
1723
+ }
1724
+ if (red >= 0 && green >= 0 && blue >= 0) {
1725
+ is_color = 1;
1726
+ if (red > 255) red = 255;
1727
+ if (green > 255) green = 255;
1728
+ if (blue > 255) blue = 255;
1729
+ }
1730
+ if (rr) *rr = red;
1731
+ if (gg) *gg = green;
1732
+ if (bb) *bb = blue;
1733
+
1734
+ /* Don't ANSI-colorize JSON output! */
1735
+ if (JSONMode) {
1736
+ is_color = 0;
1737
+ red = -1;
1738
+ green = -1;
1739
+ blue = -1;
1740
+ }
1741
+ }
1742
+
1743
+ /* Put the substituted string into the substitution buffer */
1744
+
1745
+ /* Don't use msgprefix() on RUN-type reminders */
1746
+ if (t->typ != RUN_TYPE) {
1747
+ if (UserFuncExists("msgprefix") == 1) {
1748
+ snprintf(PrioExpr, sizeof(PrioExpr), "msgprefix(%d)", t->priority);
1749
+ s = PrioExpr;
1750
+ r = EvalExpr(&s, &v, NULL);
1751
+ if (!r) {
1752
+ if (!DoCoerce(STR_TYPE, &v)) {
1753
+ if (is_color) {
1754
+ DBufPuts(&buf, Colorize(red, green, blue, 0, 1));
1755
+ }
1756
+ if (DBufPuts(&buf, v.v.str) != OK) {
1757
+ DBufFree(&buf);
1758
+ DestroyValue(v);
1759
+ return E_NO_MEM;
1760
+ }
1761
+ }
1762
+ DestroyValue(v);
1763
+ }
1764
+ }
1765
+ }
1766
+
1767
+ if (is_color) {
1768
+ DBufPuts(&buf, Colorize(red, green, blue, 0, 1));
1769
+ }
1770
+ if ( (r=DoSubst(p, &buf, t, tim, dse, NORMAL_MODE)) ) return r;
1771
+
1772
+ if (t->typ != RUN_TYPE) {
1773
+ if (UserFuncExists("msgsuffix") == 1) {
1774
+ snprintf(PrioExpr, sizeof(PrioExpr), "msgsuffix(%d)", t->priority);
1775
+ s = PrioExpr;
1776
+ r = EvalExpr(&s, &v, NULL);
1777
+ if (!r) {
1778
+ if (!DoCoerce(STR_TYPE, &v)) {
1779
+ /* Hack: If MsgSuffix starts with a backspace, move it before the newline! */
1780
+ if (*v.v.str == '\b') {
1781
+ if (DBufLen(&buf)) {
1782
+ if (DBufValue(&buf)[DBufLen(&buf)-1] == '\n') {
1783
+ /* VIOLATION of encapsulation! */
1784
+ DBufValue(&buf)[DBufLen(&buf)-1] = 0;
1785
+ buf.len--;
1786
+ adjusted_for_newline = 1;
1787
+ }
1788
+ }
1789
+ }
1790
+ if (is_color) {
1791
+ DBufPuts(&buf, Colorize(red, green, blue, 0, 1));
1792
+ }
1793
+ if (*v.v.str == '\b') {
1794
+ r = DBufPuts(&buf, v.v.str+1);
1795
+ } else {
1796
+ r = DBufPuts(&buf, v.v.str);
1797
+ }
1798
+ if (r != OK) {
1799
+ DBufFree(&buf);
1800
+ DestroyValue(v);
1801
+ return E_NO_MEM;
1802
+ }
1803
+ }
1804
+ DestroyValue(v);
1805
+ }
1806
+ }
1807
+ }
1808
+
1809
+ if (is_color) {
1810
+ DBufPuts(&buf, Decolorize());
1811
+ }
1812
+ if (adjusted_for_newline) {
1813
+ DBufPutc(&buf, '\n');
1814
+ }
1815
+
1816
+ if ((!msg_command && t->typ == MSG_TYPE) || t->typ == MSF_TYPE) {
1817
+ if (DBufPutc(&buf, '\n') != OK) {
1818
+ DBufFree(&buf);
1819
+ return E_NO_MEM;
1820
+ }
1821
+ }
1822
+
1823
+ /* If this is a dupe and we are de-duping, do nothing */
1824
+ if (DedupeReminders) {
1825
+ if (ShouldDedupe(dse, tim->ttime, DBufValue(&buf))) {
1826
+ DBufFree(&buf);
1827
+ return OK;
1828
+ }
1829
+ }
1830
+
1831
+ /* Get the url if terminal hyperlinks are enabled */
1832
+ if (TerminalHyperlinks) {
1833
+ url = FindTrigInfo(t, "url");
1834
+ } else {
1835
+ url = NULL;
1836
+ }
1837
+
1838
+ /* If we are sorting, just queue it up in the sort buffer */
1839
+ if (SortByDate) {
1840
+ if (InsertIntoSortBuffer(dse, tim->ttime, url, DBufValue(&buf),
1841
+ t->typ, t->priority) == OK) {
1842
+ DBufFree(&buf);
1843
+ NumTriggered++;
1844
+ return OK;
1845
+ }
1846
+ }
1847
+
1848
+ /* If we didn't insert the reminder into the sort buffer, issue the
1849
+ reminder now. */
1850
+ switch(t->typ) {
1851
+ case MSG_TYPE:
1852
+ case PASSTHRU_TYPE:
1853
+ if (msg_command) {
1854
+ DoMsgCommand(msg_command, DBufValue(&buf), is_queued);
1855
+ } else {
1856
+ if (output) {
1857
+ DBufPuts(output, DBufValue(&buf));
1858
+ } else {
1859
+ /* Add a space before "NOTE endreminder" */
1860
+ if (IsServerMode() && !strncmp(DBufValue(&buf), "NOTE endreminder", 16)) {
1861
+ printf(" %s", DBufValue(&buf));
1862
+ } else {
1863
+ if (url) {
1864
+ printf("\x1B]8;;%s\x1B\\", url);
1865
+ }
1866
+ printf("%s", DBufValue(&buf));
1867
+ if (url) {
1868
+ printf("\x1B]8;;\x1B\\");
1869
+ }
1870
+ }
1871
+ }
1872
+ }
1873
+ break;
1874
+
1875
+ case MSF_TYPE:
1876
+ FillParagraph(url, DBufValue(&buf), output);
1877
+ break;
1878
+
1879
+ case RUN_TYPE:
1880
+ System(DBufValue(&buf), is_queued);
1881
+ break;
1882
+
1883
+ default: /* Unknown/illegal type? */
1884
+ DBufFree(&buf);
1885
+ return E_SWERR;
1886
+ }
1887
+
1888
+ DBufFree(&buf);
1889
+ NumTriggered++;
1890
+ return OK;
1891
+ }
1892
+
1893
+ /***************************************************************/
1894
+ /* */
1895
+ /* ShouldTriggerReminder */
1896
+ /* */
1897
+ /* Return 1 if we should trigger a reminder, based on today's */
1898
+ /* date and the trigger. Return 0 if reminder should not be */
1899
+ /* triggered. Sets *err non-zero in event of an error. */
1900
+ /* */
1901
+ /***************************************************************/
1902
+ int ShouldTriggerReminder(Trigger const *t, TimeTrig const *tim, int dse, int *err)
1903
+ {
1904
+ int r, omit;
1905
+ int calmode = (DoSimpleCalendar || DoCalendar) ? 1 : 0;
1906
+ if (HideCompletedTodos) calmode = 0;
1907
+
1908
+ *err = 0;
1909
+
1910
+ /* Handle the ONCE modifier in the reminder. */
1911
+ if (!IgnoreOnce && t->once !=NO_ONCE && GetOnceDate() == DSEToday)
1912
+ return 0;
1913
+
1914
+ /* TODOs are handled differently */
1915
+ if (t->is_todo && !calmode) {
1916
+ /* Do NOT trigger if TODO has been completed through today (or later) */
1917
+ if (t->complete_through != NO_DATE && t->complete_through >= DSEToday && dse <= t->complete_through) {
1918
+ return 0;
1919
+ }
1920
+ /* DO trigger if has not been completed through trigger date */
1921
+ if (t->complete_through == NO_DATE || t->complete_through < dse) {
1922
+ /* Trigger date is in the past - overdue, Trigger unless we're
1923
+ more than max_overdue days late */
1924
+ if (dse < DSEToday) {
1925
+ if (t->max_overdue >= 0) {
1926
+ if (dse + t->max_overdue < DSEToday) {
1927
+ return 0;
1928
+ }
1929
+ }
1930
+ return 1;
1931
+ }
1932
+ /* Trigger date in future - use normal Remind rules */
1933
+ } else {
1934
+ /* We're complete as of trigger date */
1935
+ return 0;
1936
+ }
1937
+ } else {
1938
+ if (dse < DSEToday) return 0;
1939
+ }
1940
+
1941
+ /* Don't trigger timed reminders if DontIssueAts is true, and if the
1942
+ reminder is for today */
1943
+ if (dse == DSEToday && DontIssueAts && tim->ttime != NO_TIME) {
1944
+ if (DontIssueAts > 1) {
1945
+ /* If two or more -a options, then *DO* issue ats that are in the
1946
+ future */
1947
+ if (tim->ttime < MinutesPastMidnight(0)) {
1948
+ return 0;
1949
+ }
1950
+ } else {
1951
+ return 0;
1952
+ }
1953
+ }
1954
+
1955
+ /* If "infinite delta" option is chosen, always trigger future reminders */
1956
+ if (InfiniteDelta || NextMode) return 1;
1957
+
1958
+ /* If there's a "warn" function, it overrides any deltas except
1959
+ * DeltaOverride*/
1960
+ if (t->warn[0] != 0) {
1961
+ if (DeltaOverride > 0) {
1962
+ if (dse <= DSEToday + DeltaOverride) {
1963
+ return 1;
1964
+ }
1965
+ }
1966
+ return ShouldTriggerBasedOnWarn(t, dse, err);
1967
+ }
1968
+
1969
+ /* Zero delta */
1970
+ if (DeltaOverride < 0) {
1971
+ return dse == DSEToday;
1972
+ }
1973
+
1974
+ /* Move back by delta days, if any */
1975
+ if (DeltaOverride) {
1976
+ /* A positive DeltaOverride takes precedence over everything */
1977
+ dse = dse - DeltaOverride;
1978
+ } else if (t->delta != NO_DELTA) {
1979
+ if (t->delta < 0)
1980
+ dse = dse + t->delta;
1981
+ else {
1982
+ int iter = 0;
1983
+ int max = MaxSatIter;
1984
+ r = t->delta;
1985
+ if (max < r*2) max = r*2;
1986
+ while(iter++ < max) {
1987
+ if (!r || (dse <= DSEToday)) {
1988
+ break;
1989
+ }
1990
+ dse--;
1991
+ *err = IsOmitted(dse, t->localomit, t->omitfunc, &omit);
1992
+ if (*err) return 0;
1993
+ if (!omit) r--;
1994
+ }
1995
+ if (iter > max) {
1996
+ *err = E_CANT_TRIG;
1997
+ Eprint("Delta: Bad OMITFUNC? %s", GetErr(E_CANT_TRIG));
1998
+ return 0;
1999
+ }
2000
+ }
2001
+ }
2002
+
2003
+ /* Should we trigger the reminder? */
2004
+ return (dse <= DSEToday);
2005
+ }
2006
+
2007
+ /***************************************************************/
2008
+ /* */
2009
+ /* DoSatRemind */
2010
+ /* */
2011
+ /* Do the "satisfying..." remind calculation. */
2012
+ /* */
2013
+ /***************************************************************/
2014
+ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
2015
+ {
2016
+ int iter, dse, r, start;
2017
+ Value v;
2018
+ expr_node *sat_node;
2019
+ int nonconst = 0;
2020
+
2021
+ sat_node = ParseExpr(p, &r);
2022
+ if (r != OK) {
2023
+ return r;
2024
+ }
2025
+ if (!sat_node) {
2026
+ return E_SWERR;
2027
+ }
2028
+
2029
+ /* Diagnose if SAT_NODE does not reference trigdate */
2030
+ ensure_satnode_mentions_trigdate(sat_node);
2031
+
2032
+ iter = 0;
2033
+ start = get_scanfrom(trig);
2034
+ while (iter++ < MaxSatIter) {
2035
+ dse = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, 0);
2036
+ if (r) {
2037
+ free_expr_tree(sat_node);
2038
+ if (r == E_CANT_TRIG) return OK; else return r;
2039
+ }
2040
+ if (dse != start && trig->duration_days) {
2041
+ dse = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, trig->duration_days);
2042
+ if (r) {
2043
+ free_expr_tree(sat_node);
2044
+ if (r == E_CANT_TRIG) return OK; else return r;
2045
+ }
2046
+ } else if (dse == start) {
2047
+ if (tt->ttime != NO_TIME) {
2048
+ trig->eventstart = MINUTES_PER_DAY * r + tt->ttime;
2049
+ trig->eventstart_orig = trig->eventstart;
2050
+ if (tt->duration != NO_TIME) {
2051
+ trig->eventduration = tt->duration;
2052
+ }
2053
+ }
2054
+ SaveAllTriggerInfo(trig, tt, dse, tt->ttime, 1);
2055
+ }
2056
+ if (dse == -1) {
2057
+ free_expr_tree(sat_node);
2058
+ LastTrigValid = 0;
2059
+ LastTriggerDate = -1;
2060
+ return E_EXPIRED;
2061
+ }
2062
+ r = evaluate_expression(sat_node, NULL, &v, &nonconst);
2063
+ if (r) {
2064
+ free_expr_tree(sat_node);
2065
+ return r;
2066
+ }
2067
+ if (v.type != INT_TYPE && v.type != STR_TYPE) {
2068
+ free_expr_tree(sat_node);
2069
+ return E_BAD_TYPE;
2070
+ }
2071
+ if ((v.type == INT_TYPE && v.v.val) ||
2072
+ (v.type == STR_TYPE && *v.v.str)) {
2073
+ AdjustTriggerForDuration(get_scanfrom(trig), dse, trig, tt, 1);
2074
+ if (DebugFlag & DB_PRTTRIG) {
2075
+ int y, m, d;
2076
+ FromDSE(LastTriggerDate, &y, &m, &d);
2077
+ fprintf(ErrFp, "%s(%s): Trig(satisfied) = %s, %d %s, %d",
2078
+ GetCurrentFilename(), line_range(LineNoStart, LineNo),
2079
+ get_day_name(LastTriggerDate % 7),
2080
+ d,
2081
+ get_month_name(m),
2082
+ y);
2083
+ if (tt->ttime != NO_TIME) {
2084
+ fprintf(ErrFp, " AT %02d:%02d",
2085
+ (tt->ttime / 60),
2086
+ (tt->ttime % 60));
2087
+ if (tt->duration != NO_TIME) {
2088
+ fprintf(ErrFp, " DURATION %02d:%02d",
2089
+ (tt->duration / 60),
2090
+ (tt->duration % 60));
2091
+ }
2092
+ }
2093
+ fprintf(ErrFp, "\n");
2094
+ }
2095
+ free_expr_tree(sat_node);
2096
+ return OK;
2097
+ }
2098
+ if (dse+trig->duration_days < start) {
2099
+ start++;
2100
+ } else {
2101
+ start = dse+trig->duration_days+1;
2102
+ }
2103
+ }
2104
+ LastTrigValid = 0;
2105
+ free_expr_tree(sat_node);
2106
+ return E_CANT_TRIG;
2107
+ }
2108
+
2109
+ /***************************************************************/
2110
+ /* */
2111
+ /* ParsePriority - parse the PRIORITY portion of a reminder */
2112
+ /* */
2113
+ /***************************************************************/
2114
+ static int ParsePriority(ParsePtr s, Trigger *t)
2115
+ {
2116
+ int p, r;
2117
+ char const *u;
2118
+ DynamicBuffer buf;
2119
+ DBufInit(&buf);
2120
+
2121
+ r = ParseToken(s, &buf);
2122
+ if(r) return r;
2123
+ u = DBufValue(&buf);
2124
+
2125
+ if (!isdigit(*u)) {
2126
+ DBufFree(&buf);
2127
+ return E_EXPECTING_NUMBER;
2128
+ }
2129
+ p = 0;
2130
+ while (isdigit(*u)) {
2131
+ p = p*10 + *u - '0';
2132
+ u++;
2133
+ }
2134
+ if (*u) {
2135
+ DBufFree(&buf);
2136
+ return E_EXPECTING_NUMBER;
2137
+ }
2138
+
2139
+ DBufFree(&buf);
2140
+
2141
+ /* Tricky! The only way p can be < 0 is if overflow occurred; thus,
2142
+ E2HIGH is indeed the appropriate error message. */
2143
+ if (p<0 || p>9999) return E_2HIGH;
2144
+ t->priority = p;
2145
+ return OK;
2146
+ }
2147
+
2148
+ /***************************************************************/
2149
+ /* */
2150
+ /* DoMsgCommand */
2151
+ /* */
2152
+ /* Execute the '-k' command, escaping shell chars in message. */
2153
+ /* */
2154
+ /***************************************************************/
2155
+ int DoMsgCommand(char const *cmd, char const *msg, int is_queued)
2156
+ {
2157
+ int r;
2158
+ int i, l;
2159
+ DynamicBuffer execBuffer;
2160
+
2161
+ DynamicBuffer buf;
2162
+
2163
+ DBufInit(&buf);
2164
+ DBufInit(&execBuffer);
2165
+
2166
+ /* Escape shell characters in msg */
2167
+ if (ShellEscape(msg, &buf) != OK) {
2168
+ r = E_NO_MEM;
2169
+ goto finished;
2170
+ }
2171
+
2172
+ msg = DBufValue(&buf);
2173
+
2174
+ /* Do "%s" substitution */
2175
+ l = strlen(cmd);
2176
+ for (i=0; i<l; i++) {
2177
+ if (cmd[i] == '%' && cmd[i+1] == 's') {
2178
+ ++i;
2179
+ if (DBufPuts(&execBuffer, msg) != OK) {
2180
+ r = E_NO_MEM;
2181
+ goto finished;
2182
+ }
2183
+ } else {
2184
+ if (DBufPutc(&execBuffer, cmd[i]) != OK) {
2185
+ r = E_NO_MEM;
2186
+ goto finished;
2187
+ }
2188
+ }
2189
+ }
2190
+ r = OK;
2191
+
2192
+ System(DBufValue(&execBuffer), is_queued);
2193
+
2194
+ finished:
2195
+ DBufFree(&buf);
2196
+ DBufFree(&execBuffer);
2197
+ return r;
2198
+ }
2199
+
2200
+ /***************************************************************/
2201
+ /* */
2202
+ /* ShouldTriggerBasedOnWarn */
2203
+ /* */
2204
+ /* Determine whether to trigger a reminder based on its WARN */
2205
+ /* function. */
2206
+ /* */
2207
+ /***************************************************************/
2208
+ static int ShouldTriggerBasedOnWarn(Trigger const *t, int dse, int *err)
2209
+ {
2210
+ char buffer[VAR_NAME_LEN+32];
2211
+ int i;
2212
+ char const *s;
2213
+ int r, omit;
2214
+ Value v;
2215
+ int lastReturnVal = 0; /* Silence compiler warning */
2216
+ int calmode = (DoSimpleCalendar || DoCalendar) ? 1 : 0;
2217
+
2218
+ /* TODOs are handled differently */
2219
+ if (t->is_todo && !calmode) {
2220
+ /* Do NOT trigger if TODO has been completed through today (or later) */
2221
+ if (t->complete_through != NO_DATE && t->complete_through >= DSEToday) {
2222
+ return 0;
2223
+ }
2224
+ /* DO trigger if has not been completed through trigger date */
2225
+ if (t->complete_through == NO_DATE || t->complete_through < dse) {
2226
+ /* Trigger date is in the past - overdue, Trigger unless we're
2227
+ more than max_overdue days late */
2228
+ if (dse < DSEToday) {
2229
+ if (t->max_overdue >= 0) {
2230
+ if (dse + t->max_overdue < DSEToday) {
2231
+ return 0;
2232
+ }
2233
+ }
2234
+ return 1;
2235
+ }
2236
+ /* Trigger date in future - use normal Remind rules */
2237
+ } else {
2238
+ /* We're complete as of trigger date */
2239
+ return 0;
2240
+ }
2241
+ }
2242
+
2243
+ /* If no proper function exists, barf... */
2244
+ if (UserFuncExists(t->warn) != 1) {
2245
+ Eprint("%s: `%s'", GetErr(M_BAD_WARN_FUNC), t->warn);
2246
+ return (dse == DSEToday);
2247
+ }
2248
+ for (i=1; ; i++) {
2249
+ snprintf(buffer, sizeof(buffer), "%s(%d)", t->warn, i);
2250
+ s = buffer;
2251
+ r = EvalExpr(&s, &v, NULL);
2252
+ if (r) {
2253
+ Eprint("%s: `%s': %s", GetErr(M_BAD_WARN_FUNC),
2254
+ t->warn, GetErr(r));
2255
+ return (dse == DSEToday);
2256
+ }
2257
+ if (v.type != INT_TYPE) {
2258
+ DestroyValue(v);
2259
+ Eprint("%s: `%s': %s", GetErr(M_BAD_WARN_FUNC),
2260
+ t->warn, GetErr(E_BAD_TYPE));
2261
+ return (dse == DSEToday);
2262
+ }
2263
+
2264
+ /* If absolute value of return is not monotonically
2265
+ decreasing, exit */
2266
+ if (i > 1 && abs(v.v.val) >= lastReturnVal) {
2267
+ return (dse == DSEToday);
2268
+ }
2269
+
2270
+ lastReturnVal = abs(v.v.val);
2271
+ /* Positive values: Just subtract. Negative values:
2272
+ skip omitted days. */
2273
+ if (v.v.val >= 0) {
2274
+ if (DSEToday + v.v.val == dse) return 1;
2275
+ } else {
2276
+ int j = dse;
2277
+ int iter = 0;
2278
+ int max = MaxSatIter;
2279
+ if (max < v.v.val * 2) max = v.v.val*2;
2280
+ while(iter++ <= max) {
2281
+ j--;
2282
+ *err = IsOmitted(j, t->localomit, t->omitfunc, &omit);
2283
+ if (*err) {
2284
+ return (dse == DSEToday);
2285
+ }
2286
+ if (!omit) v.v.val++;
2287
+ if (!v.v.val) {
2288
+ break;
2289
+ }
2290
+ }
2291
+ if (iter > max) {
2292
+ Eprint("Delta: Bad OMITFUNC? %s", GetErr(E_CANT_TRIG));
2293
+ return (dse == DSEToday);
2294
+ }
2295
+ if (j == DSEToday) return 1;
2296
+ }
2297
+ }
2298
+ }
2299
+
2300
+ void FixSpecialType(Trigger *t)
2301
+ {
2302
+ if (t->typ != PASSTHRU_TYPE) {
2303
+ return;
2304
+ }
2305
+
2306
+ /* Convert SPECIAL MSG / MSF / RUN / CAL to just plain MSG / MSF / etc */
2307
+ if (!strcasecmp(t->passthru, "MSG")) {
2308
+ t->typ = MSG_TYPE;
2309
+ } else if (!strcasecmp(t->passthru, "MSF")) {
2310
+ t->typ = MSF_TYPE;
2311
+ } else if (!strcasecmp(t->passthru, "RUN")) {
2312
+ t->typ = RUN_TYPE;
2313
+ } else if (!strcasecmp(t->passthru, "CAL")) {
2314
+ t->typ = CAL_TYPE;
2315
+ } else if (!strcasecmp(t->passthru, "PS")) {
2316
+ t->typ = PS_TYPE;
2317
+ } else if (!strcasecmp(t->passthru, "PSFILE")) {
2318
+ t->typ = PSF_TYPE;
2319
+ }
2320
+ }
2321
+
2322
+ static int
2323
+ ShouldQueueReminder(Trigger const *t, TimeTrig const *tim, int dse)
2324
+ {
2325
+ int sched_is_close_enough = 0;
2326
+ int r;
2327
+
2328
+ if (DontQueue) {
2329
+ return 0;
2330
+ }
2331
+ if (t->noqueue) {
2332
+ return 0;
2333
+ }
2334
+ if (tim->ttime == NO_TIME) {
2335
+ return 0;
2336
+ }
2337
+ if (t->typ == CAL_TYPE) {
2338
+ return 0;
2339
+ }
2340
+ if (t->typ == RUN_TYPE && RunDisabled) {
2341
+ return 0;
2342
+ }
2343
+
2344
+ if (dse * MINUTES_PER_DAY + tim->ttime < SystemDateTime(0)) {
2345
+ return 0;
2346
+ }
2347
+
2348
+ /* If we have a sched function, calculate how far back it goes */
2349
+ if (t->sched[0] && UserFuncExists(t->sched) == 1) {
2350
+ char exprBuf[VAR_NAME_LEN+32];
2351
+ char const *s = exprBuf;
2352
+ Value v;
2353
+ int advance_dse;
2354
+
2355
+ snprintf(exprBuf, sizeof(exprBuf), "%s(1)", t->sched);
2356
+ if (RunDisabled) {
2357
+ r = EvalExprRunDisabled(&s, &v, NULL);
2358
+ } else {
2359
+ r = EvalExpr(&s, &v, NULL);
2360
+ }
2361
+ if (r == 0) {
2362
+ if (v.type == TIME_TYPE || v.type == INT_TYPE) {
2363
+ advance_dse = dse * MINUTES_PER_DAY + v.v.val;
2364
+ } else {
2365
+ advance_dse = dse * MINUTES_PER_DAY + tim->ttime;
2366
+ }
2367
+ DestroyValue(v);
2368
+ if (advance_dse <= DSEToday * MINUTES_PER_DAY + MINUTES_PER_DAY - 1) {
2369
+ sched_is_close_enough = 1;
2370
+ }
2371
+ }
2372
+ }
2373
+ if (!sched_is_close_enough &&
2374
+ dse * MINUTES_PER_DAY + tim->ttime - tim->delta > DSEToday * MINUTES_PER_DAY + MINUTES_PER_DAY - 1) {
2375
+ /* Too far in the future */
2376
+ return 0;
2377
+ }
2378
+
2379
+ if (todo_filtered(t)) {
2380
+ return 0;
2381
+ }
2382
+ if (IgnoreOnce) {
2383
+ return 1;
2384
+ }
2385
+ if (t->once == NO_ONCE || GetOnceDate() != DSEToday) {
2386
+ return 1;
2387
+ }
2388
+ return 0;
2389
+ }