reparser.y 21 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079
  1. /* $XConsortium: reparser.y /main/2 1996/11/11 11:52:15 drk $ */
  2. %{
  3. /*
  4. * (c) Copyright 1993, 1994 Hewlett-Packard Company
  5. * (c) Copyright 1993, 1994 International Business Machines Corp.
  6. * (c) Copyright 1993, 1994 Novell, Inc.
  7. * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  8. */
  9. #include <EUSCompat.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14. #include <time.h>
  15. #include "rerule.h"
  16. #include "iso8601.h"
  17. /* The parsed rule is stored in this structure */
  18. RepeatEvent *_DtCm_repeat_info;
  19. extern int yylex(void);
  20. extern void yyerror(char*);
  21. static int CompareNums(const void *, const void *);
  22. static int CompareDayTime(const void *, const void *);
  23. static int CompareWeekDayTime(const void *, const void *);
  24. static unsigned int *ConvertNumList(NumberList *, unsigned int * /* Return */);
  25. static WeekDayTime *ConvertWeekDayTime(WeekDayTimeList *, unsigned int *);
  26. static NumberList *AllocNumber(unsigned int);
  27. static WeekDayTimeList *AllocWeekDayTimeList(NumberList*, NumberList *,
  28. NumberList *);
  29. static RepeatEvent *HandleEndDate(RepeatEvent *, time_t);
  30. static RepeatEvent *DeriveMinuteEvent(unsigned int, unsigned int);
  31. static RepeatEvent *DeriveDailyEvent(unsigned int, NumberList *,
  32. unsigned int, RepeatEvent *);
  33. static RepeatEvent *DeriveWeeklyEvent(unsigned int, DayTimeList *,
  34. unsigned int, RepeatEvent *);
  35. static RepeatEvent *DeriveMonthlyEvent(RepeatType, unsigned int, void *,
  36. unsigned int, RepeatEvent *);
  37. static RepeatEvent *DeriveYearlyEvent(RepeatType, unsigned int, NumberList *,
  38. unsigned int, RepeatEvent *);
  39. %}
  40. %token ERROR ENDMARKER DURATION NUMBER FIRSTWEEK SECONDWEEK THIRDWEEK
  41. %token FOURTHWEEK FIFTHWEEK LASTWEEK SECONDLAST THIRDLAST FOURTHLAST
  42. %token FIFTHLAST MINUTECOMMAND DAILYCOMMAND WEEKLYCOMMAND MONTHPOSCOMMAND
  43. %token MONTHDAYCOMMAND YEARDAYCOMMAND YEARMONTHCOMMAND LASTDAY SUNDAY
  44. %token MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY DATE
  45. %union {
  46. int number;
  47. RepeatEvent *re;
  48. NumberList *nl;
  49. WeekDay weekday;
  50. WeekNumber weeknum;
  51. DayTime *dt;
  52. DayTimeList *dtl;
  53. WeekDayTimeList *wdtl;
  54. time_t enddate;
  55. char date[64];
  56. }
  57. %type <re> start begin minuteEvent dailyEvent weeklyEvent monthlyPosEvent
  58. monthlyDayEvent yearlyByMonth yearlyByDay
  59. %type <nl> time0List timeList dayOfMonthList monthOfYearList
  60. dayOfYearList occurrenceList genericNumberList
  61. generic0NumberList weekdayList
  62. %type <weekday> SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY
  63. weekday
  64. %type <number> duration NUMBER occurrence endMarker time
  65. %type <dtl> weekdayTimeList
  66. %type <wdtl> weekDayTime
  67. %type <dt> weekdayTimePair
  68. %type <date> DATE
  69. %type <enddate> endDate
  70. %% /* Beginning of rules section */
  71. start : begin
  72. {
  73. _DtCm_repeat_info = $$;
  74. }
  75. | error
  76. {
  77. /*
  78. * XXX: Memory leak: We need to free up any portion
  79. * of the re struct that has be allocated before the
  80. * error was encountered.
  81. */
  82. _DtCm_repeat_info = NULL;
  83. }
  84. ;
  85. begin : minuteEvent endDate
  86. {
  87. $$ = HandleEndDate($1, $2);
  88. }
  89. | dailyEvent endDate
  90. {
  91. $$ = HandleEndDate($1, $2);
  92. }
  93. | weeklyEvent endDate
  94. {
  95. $$ = HandleEndDate($1, $2);
  96. }
  97. | monthlyPosEvent endDate
  98. {
  99. $$ = HandleEndDate($1, $2);
  100. }
  101. | monthlyDayEvent endDate
  102. {
  103. $$ = HandleEndDate($1, $2);
  104. }
  105. | yearlyByMonth endDate
  106. {
  107. $$ = HandleEndDate($1, $2);
  108. }
  109. | yearlyByDay endDate
  110. {
  111. $$ = HandleEndDate($1, $2);
  112. }
  113. ;
  114. minuteEvent : /* empty */
  115. {
  116. $$ = NULL;
  117. }
  118. | MINUTECOMMAND NUMBER duration
  119. {
  120. #ifdef MINUTE
  121. $$ = DeriveMinuteEvent($2, $3);
  122. #else
  123. $$ = NULL;
  124. #endif /* MINUTE */
  125. }
  126. ;
  127. dailyEvent
  128. : DAILYCOMMAND NUMBER time0List duration minuteEvent
  129. {
  130. $$ = DeriveDailyEvent($2, $3, $4, $5);
  131. if ($5) $$ = NULL;
  132. }
  133. ;
  134. weeklyEvent
  135. : WEEKLYCOMMAND NUMBER weekdayTimeList duration minuteEvent
  136. {
  137. $$ = DeriveWeeklyEvent($2, $3, $4, $5);
  138. if ($5) $$ = NULL;
  139. }
  140. | WEEKLYCOMMAND NUMBER duration minuteEvent
  141. {
  142. $$ = DeriveWeeklyEvent($2, NULL, $3, $4);
  143. if ($4) $$ = NULL;
  144. }
  145. ;
  146. monthlyPosEvent
  147. : MONTHPOSCOMMAND NUMBER weekDayTime duration minuteEvent
  148. {
  149. $$ = DeriveMonthlyEvent(RT_MONTHLY_POSITION,
  150. $2, $3, $4, $5);
  151. if ($5) $$ = NULL;
  152. }
  153. | MONTHPOSCOMMAND NUMBER weekDayTime duration dailyEvent
  154. {
  155. $$ = DeriveMonthlyEvent(RT_MONTHLY_POSITION,
  156. $2, $3, $4, $5);
  157. if ($5) $$ = NULL;
  158. }
  159. | MONTHPOSCOMMAND NUMBER weekDayTime duration weeklyEvent
  160. {
  161. $$ = DeriveMonthlyEvent(RT_MONTHLY_POSITION,
  162. $2, $3, $4, $5);
  163. if ($5) $$ = NULL;
  164. }
  165. ;
  166. monthlyDayEvent : MONTHDAYCOMMAND NUMBER dayOfMonthList duration minuteEvent
  167. {
  168. $$ = DeriveMonthlyEvent(RT_MONTHLY_DAY, $2, $3, $4, $5);
  169. if ($5) $$ = NULL;
  170. }
  171. | MONTHDAYCOMMAND NUMBER dayOfMonthList duration dailyEvent
  172. {
  173. $$ = DeriveMonthlyEvent(RT_MONTHLY_DAY, $2, $3, $4, $5);
  174. if ($5) $$ = NULL;
  175. }
  176. | MONTHDAYCOMMAND NUMBER dayOfMonthList duration weeklyEvent
  177. {
  178. $$ = DeriveMonthlyEvent(RT_MONTHLY_DAY, $2, $3, $4, $5);
  179. if ($5) $$ = NULL;
  180. }
  181. ;
  182. yearlyByMonth : YEARMONTHCOMMAND NUMBER monthOfYearList duration minuteEvent
  183. {
  184. $$ = DeriveYearlyEvent(RT_YEARLY_MONTH, $2, $3, $4, $5);
  185. if ($5) $$ = NULL;
  186. }
  187. | YEARMONTHCOMMAND NUMBER monthOfYearList duration dailyEvent
  188. {
  189. $$ = DeriveYearlyEvent(RT_YEARLY_MONTH, $2, $3, $4, $5);
  190. if ($5) $$ = NULL;
  191. }
  192. | YEARMONTHCOMMAND NUMBER monthOfYearList duration weeklyEvent
  193. {
  194. $$ = DeriveYearlyEvent(RT_YEARLY_MONTH, $2, $3, $4, $5);
  195. if ($5) $$ = NULL;
  196. }
  197. | YEARMONTHCOMMAND NUMBER monthOfYearList duration
  198. monthlyPosEvent
  199. {
  200. $$ = DeriveYearlyEvent(RT_YEARLY_MONTH, $2, $3, $4, $5);
  201. if ($5) $$ = NULL;
  202. }
  203. | YEARMONTHCOMMAND NUMBER monthOfYearList duration
  204. monthlyDayEvent
  205. {
  206. $$ = DeriveYearlyEvent(RT_YEARLY_MONTH, $2, $3, $4, $5);
  207. if ($5) $$ = NULL;
  208. }
  209. ;
  210. yearlyByDay : YEARDAYCOMMAND NUMBER dayOfYearList duration minuteEvent
  211. {
  212. $$ = DeriveYearlyEvent(RT_YEARLY_DAY, $2, $3, $4, $5);
  213. if ($5) $$ = NULL;
  214. }
  215. | YEARDAYCOMMAND NUMBER dayOfYearList duration dailyEvent
  216. {
  217. $$ = DeriveYearlyEvent(RT_YEARLY_DAY, $2, $3, $4, $5);
  218. if ($5) $$ = NULL;
  219. }
  220. | YEARDAYCOMMAND NUMBER dayOfYearList duration weeklyEvent
  221. {
  222. $$ = DeriveYearlyEvent(RT_YEARLY_DAY, $2, $3, $4, $5);
  223. if ($5) $$ = NULL;
  224. }
  225. | YEARDAYCOMMAND NUMBER dayOfYearList duration monthlyPosEvent
  226. {
  227. $$ = DeriveYearlyEvent(RT_YEARLY_DAY, $2, $3, $4, $5);
  228. if ($5) $$ = NULL;
  229. }
  230. | YEARDAYCOMMAND NUMBER dayOfYearList duration monthlyDayEvent
  231. {
  232. $$ = DeriveYearlyEvent(RT_YEARLY_DAY, $2, $3, $4, $5);
  233. if ($5) $$ = NULL;
  234. }
  235. ;
  236. /* e.g. 1W MO TU 1300 1400 */
  237. weekDayTime : /* empty */
  238. {
  239. $$ = NULL;
  240. }
  241. | weekDayTime occurrenceList weekdayList
  242. {
  243. WeekDayTimeList *wdtl;
  244. wdtl = AllocWeekDayTimeList($2, $3, NULL);
  245. if ($1 == NULL) {
  246. $$ = wdtl;
  247. } else {
  248. wdtl->wdtl_next = $$->wdtl_next;
  249. $$->wdtl_next = wdtl;
  250. }
  251. }
  252. | weekDayTime occurrenceList weekdayList timeList
  253. {
  254. WeekDayTimeList *wdtl;
  255. wdtl = AllocWeekDayTimeList($2, $3, $4);
  256. if ($1 == NULL) {
  257. $$ = wdtl;
  258. } else {
  259. wdtl->wdtl_next = $$->wdtl_next;
  260. $$->wdtl_next = wdtl;
  261. }
  262. }
  263. ;
  264. /* e.g. MO TU WE TH */
  265. weekdayList : weekday
  266. {
  267. $$ = AllocNumber($1);
  268. }
  269. | weekdayList weekday
  270. {
  271. NumberList *nl;
  272. nl = AllocNumber($2);
  273. if ($1 == NULL) {
  274. $$ = nl;
  275. } else {
  276. nl->nl_next = $$->nl_next;
  277. $$->nl_next = nl;
  278. }
  279. }
  280. ;
  281. /* e.g. 1W 3W 2L LW */
  282. occurrenceList : occurrence
  283. {
  284. $$ = AllocNumber($1);
  285. }
  286. | occurrenceList occurrence
  287. {
  288. NumberList *nl;
  289. nl = AllocNumber($2);
  290. if ($1 == NULL) {
  291. $$ = nl;
  292. } else {
  293. nl->nl_next = $$->nl_next;
  294. $$->nl_next = nl;
  295. }
  296. }
  297. ;
  298. /* e.g. MO 1300 1500 2000 */
  299. weekdayTimePair : weekday time0List
  300. {
  301. DayTime *dt;
  302. dt = (DayTime *)calloc(1, sizeof(DayTime));
  303. dt->dt_day = $1;
  304. /* Convert from list to array, sort */
  305. dt->dt_time =
  306. (Time *)ConvertNumList($2, &(dt->dt_ntime));
  307. $$ = dt;
  308. }
  309. ;
  310. /* e.g. MO 1300 1500 2000 TU 1200 1400 */
  311. weekdayTimeList : weekdayTimePair
  312. {
  313. DayTimeList *dtl;
  314. dtl = (DayTimeList *)calloc(1, sizeof(DayTimeList));
  315. dtl->dtl_daytime = $1;
  316. dtl->dtl_next = NULL;
  317. $$ = dtl;
  318. }
  319. | weekdayTimeList weekdayTimePair
  320. {
  321. DayTimeList *dtl,
  322. *dtl_end;
  323. dtl = (DayTimeList *)calloc(1, sizeof(DayTimeList));
  324. dtl->dtl_daytime = $2;
  325. dtl->dtl_next = NULL;
  326. if ($1 == NULL) {
  327. $$ = dtl;
  328. } else {
  329. /* Insert the new entry at the end. This is
  330. * so that MO TU 200 300 TH will maintain the
  331. * same order in the list since MO uses the
  332. * times next to TU and TH is dependent on the
  333. * appt time.
  334. */
  335. dtl_end = $$;
  336. while (dtl_end->dtl_next)
  337. dtl_end = dtl_end->dtl_next;
  338. dtl_end->dtl_next = dtl;
  339. }
  340. }
  341. ;
  342. /* e.g. 1+ 2+ 3- 1- */
  343. occurrence : FIRSTWEEK endMarker
  344. {
  345. $$ = WK_F1;
  346. if ($2) RE_SET_FLAG($$);
  347. }
  348. | SECONDWEEK endMarker
  349. {
  350. $$ = WK_F2;
  351. if ($2) RE_SET_FLAG($$);
  352. }
  353. | THIRDWEEK endMarker
  354. {
  355. $$ = WK_F3;
  356. if ($2) RE_SET_FLAG($$);
  357. }
  358. | FOURTHWEEK endMarker
  359. {
  360. $$ = WK_F4;
  361. if ($2) RE_SET_FLAG($$);
  362. }
  363. | FIFTHWEEK endMarker
  364. {
  365. $$ = WK_F5;
  366. if ($2) RE_SET_FLAG($$);
  367. }
  368. | LASTWEEK endMarker
  369. {
  370. $$ = WK_L1;
  371. if ($2) RE_SET_FLAG($$);
  372. }
  373. | SECONDLAST endMarker
  374. {
  375. $$ = WK_L2;
  376. if ($2) RE_SET_FLAG($$);
  377. }
  378. | THIRDLAST endMarker
  379. {
  380. $$ = WK_L3;
  381. if ($2) RE_SET_FLAG($$);
  382. }
  383. | FOURTHLAST endMarker
  384. {
  385. $$ = WK_L4;
  386. if ($2) RE_SET_FLAG($$);
  387. }
  388. | FIFTHLAST endMarker
  389. {
  390. $$ = WK_L5;
  391. if ($2) RE_SET_FLAG($$);
  392. }
  393. ;
  394. endDate : /* empty */
  395. {
  396. $$ = '\0';
  397. }
  398. | DATE
  399. {
  400. if (_csa_iso8601_to_tick($1, &$$) == -1)
  401. $$ = '\0';
  402. }
  403. ;
  404. /* e.g. MO TU WE */
  405. weekday : SUNDAY endMarker
  406. {
  407. $$ = WD_SUN;
  408. if ($2) RE_SET_FLAG($$);
  409. }
  410. | MONDAY endMarker
  411. {
  412. $$ = WD_MON;
  413. if ($2) RE_SET_FLAG($$);
  414. }
  415. | TUESDAY endMarker
  416. {
  417. $$ = WD_TUE;
  418. if ($2) RE_SET_FLAG($$);
  419. }
  420. | WEDNESDAY endMarker
  421. {
  422. $$ = WD_WED;
  423. if ($2) RE_SET_FLAG($$);
  424. }
  425. | THURSDAY endMarker
  426. {
  427. $$ = WD_THU;
  428. if ($2) RE_SET_FLAG($$);
  429. }
  430. | FRIDAY endMarker
  431. {
  432. $$ = WD_FRI;
  433. if ($2) RE_SET_FLAG($$);
  434. }
  435. | SATURDAY endMarker
  436. {
  437. $$ = WD_SAT;
  438. if ($2) RE_SET_FLAG($$);
  439. }
  440. ;
  441. /* e.g. 0100 1200 1300 or NULL */
  442. time0List : /* empty */
  443. {
  444. $$ = NULL;
  445. }
  446. | time0List time
  447. {
  448. NumberList *nl;
  449. nl = AllocNumber($2);
  450. if ($1 == NULL) {
  451. $$ = nl;
  452. } else {
  453. nl->nl_next = $$->nl_next;
  454. $$->nl_next = nl;
  455. }
  456. }
  457. ;
  458. /* e.g. 1000 */
  459. time : NUMBER endMarker
  460. {
  461. if ($2)
  462. RE_SET_FLAG($1);
  463. $$ = $1;
  464. }
  465. ;
  466. /* e.g. $ */
  467. endMarker : /* empty */
  468. {
  469. $$ = FALSE;
  470. }
  471. | ENDMARKER
  472. {
  473. $$ = TRUE;
  474. }
  475. ;
  476. /* e.g. #10 */
  477. duration : /* empty */
  478. {
  479. /* If no duration then default to 2 - set later if
  480. * end date not used.
  481. */
  482. $$ = RE_NOTSET;
  483. }
  484. | DURATION NUMBER
  485. {
  486. /* If duration == 0 then repeat forever */
  487. if ($2 == 0)
  488. $$ = RE_INFINITY;
  489. else
  490. $$ = $2;
  491. }
  492. ;
  493. timeList : genericNumberList
  494. dayOfMonthList : generic0NumberList
  495. monthOfYearList : generic0NumberList
  496. dayOfYearList : generic0NumberList
  497. generic0NumberList: /* empty */
  498. {
  499. $$ = NULL;
  500. }
  501. | genericNumberList
  502. {
  503. $$ = $1;
  504. }
  505. genericNumberList
  506. : NUMBER endMarker
  507. {
  508. if ($2)
  509. RE_SET_FLAG($1);
  510. $$ = AllocNumber($1);
  511. }
  512. | LASTDAY endMarker
  513. {
  514. int number = RE_LASTDAY;
  515. if ($2)
  516. RE_SET_FLAG(number);
  517. $$ = AllocNumber(number);
  518. }
  519. | genericNumberList NUMBER endMarker
  520. {
  521. NumberList *nl;
  522. if ($3)
  523. RE_SET_FLAG($2);
  524. nl = AllocNumber($2);
  525. if ($1 == NULL) {
  526. $$ = nl;
  527. } else {
  528. nl->nl_next = $$->nl_next;
  529. $$->nl_next = nl;
  530. }
  531. }
  532. | genericNumberList LASTDAY endMarker
  533. {
  534. NumberList *nl;
  535. int number = RE_LASTDAY;
  536. if ($3)
  537. RE_SET_FLAG(number);
  538. nl = AllocNumber(number);
  539. if ($1 == NULL) {
  540. $$ = nl;
  541. } else {
  542. nl->nl_next = $$->nl_next;
  543. $$->nl_next = nl;
  544. }
  545. }
  546. ;
  547. %%
  548. /*
  549. * Convert the NumberList (linked list) to an array, sort the array.
  550. */
  551. static unsigned int *
  552. ConvertNumList(
  553. NumberList *nl,
  554. unsigned int *count)
  555. {
  556. NumberList *nl_head = nl;
  557. unsigned int *array;
  558. int i = 0;
  559. if (!nl) return (unsigned int *)NULL;
  560. while (nl) {
  561. i++;
  562. nl = nl->nl_next;
  563. }
  564. array = (unsigned int *) calloc(i, sizeof(unsigned int));
  565. i = 0;
  566. /* Convert the list into an array */
  567. nl = nl_head;
  568. while (nl) {
  569. NumberList *nl_prev;
  570. array[i] = nl->nl_number;
  571. i++;
  572. nl_prev = nl;
  573. nl = nl->nl_next;
  574. free(nl_prev);
  575. }
  576. *count = i;
  577. /* Sort the array */
  578. qsort((void *)array, i, sizeof(unsigned int), CompareNums);
  579. return array;
  580. }
  581. /*
  582. * Convert the DayTimeList to an array, sort the array.
  583. */
  584. static DayTime *
  585. ConvertDayTime(
  586. DayTimeList *dtl,
  587. unsigned int *count)
  588. {
  589. DayTimeList *dtl_head = dtl;
  590. DayTime *daytime_array;
  591. int i = 0,
  592. no_time = -1;
  593. if (!dtl) return (DayTime *)NULL;
  594. while (dtl) {
  595. i++;
  596. dtl = dtl->dtl_next;
  597. }
  598. daytime_array = (DayTime *) calloc(i, sizeof(DayTime));
  599. i = 0;
  600. /* Convert the list into an array */
  601. dtl = dtl_head;
  602. while (dtl) {
  603. DayTimeList *dtl_prev;
  604. daytime_array[i].dt_day = dtl->dtl_daytime->dt_day;
  605. daytime_array[i].dt_ntime = dtl->dtl_daytime->dt_ntime;
  606. daytime_array[i].dt_time = dtl->dtl_daytime->dt_time;
  607. i++;
  608. dtl_prev = dtl;
  609. dtl = dtl->dtl_next;
  610. /* alloc'ed in <weekdayTimeList> */
  611. free(dtl_prev);
  612. }
  613. *count = i;
  614. for (i = 0; i < *count; i++) {
  615. if (daytime_array[i].dt_time == NULL) {
  616. if (no_time == -1)
  617. no_time = i;
  618. } else {
  619. if (no_time != -1) {
  620. int j;
  621. for (j = no_time; j < i; j++) {
  622. daytime_array[j].dt_ntime =
  623. daytime_array[i].dt_ntime;
  624. daytime_array[j].dt_time =
  625. (Time *)calloc(
  626. daytime_array[j].dt_ntime,
  627. sizeof(Time));
  628. memcpy(daytime_array[j].dt_time,
  629. daytime_array[i].dt_time,
  630. daytime_array[j].dt_ntime *
  631. sizeof(Time));
  632. }
  633. no_time = -1;
  634. }
  635. }
  636. }
  637. /* Sort the array */
  638. qsort((void *)daytime_array, *count, sizeof(DayTime), CompareDayTime);
  639. return daytime_array;
  640. }
  641. /*
  642. * Used by qsort()
  643. */
  644. static int
  645. CompareNums(
  646. const void *data1,
  647. const void *data2)
  648. {
  649. const unsigned int *i = (const unsigned int *)data1;
  650. const unsigned int *j = (const unsigned int *)data2;
  651. if ((unsigned )RE_MASK_STOP(*i) > (unsigned )RE_MASK_STOP(*j))
  652. return(1);
  653. if ((unsigned )RE_MASK_STOP(*i) < (unsigned )RE_MASK_STOP(*j))
  654. return(-1);
  655. return (0);
  656. }
  657. /*
  658. * Used by qsort()
  659. */
  660. static int
  661. CompareDayTime(
  662. const void *data1,
  663. const void *data2)
  664. {
  665. const DayTime *i = (const DayTime *)data1;
  666. const DayTime *j = (const DayTime *)data2;
  667. if ((unsigned )RE_MASK_STOP(i->dt_day) >
  668. (unsigned )RE_MASK_STOP(j->dt_day))
  669. return(1);
  670. if ((unsigned )RE_MASK_STOP(i->dt_day) <
  671. (unsigned )RE_MASK_STOP(j->dt_day))
  672. return(-1);
  673. return (0);
  674. }
  675. /*
  676. * Used by qsort()
  677. */
  678. static int
  679. CompareWeekDayTime(
  680. const void *data1,
  681. const void *data2)
  682. {
  683. const WeekDayTime *i = (const WeekDayTime *)data1;
  684. const WeekDayTime *j = (const WeekDayTime *)data2;
  685. if ((unsigned )RE_MASK_STOP(i->wdt_week[0]) >
  686. (unsigned )RE_MASK_STOP(j->wdt_week[0]))
  687. return(1);
  688. if ((unsigned )RE_MASK_STOP(i->wdt_week[0]) <
  689. (unsigned )RE_MASK_STOP(j->wdt_week[0]))
  690. return(-1);
  691. return (0);
  692. }
  693. static NumberList *
  694. AllocNumber(
  695. unsigned int num)
  696. {
  697. NumberList *nl;
  698. nl = (NumberList *)calloc(1, sizeof(NumberList));
  699. nl->nl_number = num;
  700. nl->nl_next = NULL;
  701. return nl;
  702. }
  703. /*
  704. * Given three NumberLists convert them into arrays and return a WeekDayTime.
  705. */
  706. static WeekDayTimeList *
  707. AllocWeekDayTimeList(
  708. NumberList *week_list,
  709. NumberList *day_list,
  710. NumberList *time_list)
  711. {
  712. WeekDayTime *wdt;
  713. WeekDayTimeList *wdtl;
  714. wdt = (WeekDayTime *)calloc(1, sizeof(WeekDayTime));
  715. wdtl = (WeekDayTimeList *)calloc(1, sizeof(WeekDayTimeList));
  716. wdt->wdt_week =
  717. (WeekNumber *)ConvertNumList(week_list, &(wdt->wdt_nweek));
  718. wdt->wdt_day =
  719. (WeekDay *)ConvertNumList(day_list, &(wdt->wdt_nday));
  720. wdt->wdt_time =
  721. (Time *)ConvertNumList(time_list, &(wdt->wdt_ntime));
  722. wdtl->wdtl_weektime = wdt;
  723. return wdtl;
  724. }
  725. /*
  726. * Convert the DayTimeList to an array, sort the array.
  727. */
  728. static WeekDayTime *
  729. ConvertWeekDayTime(
  730. WeekDayTimeList *wdtl,
  731. unsigned int *count)
  732. {
  733. WeekDayTimeList *wdtl_head = wdtl;
  734. WeekDayTime *array;
  735. int i = 0;
  736. if (!wdtl) return (WeekDayTime *)NULL;
  737. while (wdtl) {
  738. i++;
  739. wdtl = wdtl->wdtl_next;
  740. }
  741. array = (WeekDayTime *) calloc(i, sizeof(WeekDayTime));
  742. i = 0;
  743. /* Convert the list into an array */
  744. wdtl = wdtl_head;
  745. while (wdtl) {
  746. WeekDayTimeList *wdtl_prev;
  747. array[i].wdt_day = wdtl->wdtl_weektime->wdt_day;
  748. array[i].wdt_nday = wdtl->wdtl_weektime->wdt_nday;
  749. array[i].wdt_time = wdtl->wdtl_weektime->wdt_time;
  750. array[i].wdt_ntime = wdtl->wdtl_weektime->wdt_ntime;
  751. array[i].wdt_week = wdtl->wdtl_weektime->wdt_week;
  752. array[i].wdt_nweek = wdtl->wdtl_weektime->wdt_nweek;
  753. i++;
  754. wdtl_prev = wdtl;
  755. wdtl = wdtl->wdtl_next;
  756. free(wdtl_prev);
  757. }
  758. *count = i;
  759. /* Sort the array */
  760. qsort((void *)array, i, sizeof(WeekDayTime), CompareWeekDayTime);
  761. return array;
  762. }
  763. static RepeatEvent *
  764. HandleEndDate(
  765. RepeatEvent *re,
  766. time_t enddate)
  767. {
  768. if (re) {
  769. if (enddate) {
  770. re->re_end_date = enddate;
  771. } else if (re->re_duration == RE_NOTSET) {
  772. re->re_duration = 2;
  773. }
  774. }
  775. return re;
  776. }
  777. /*
  778. * Create a RepeatEvent for the minute portion of a rule.
  779. */
  780. static RepeatEvent *
  781. DeriveMinuteEvent(
  782. unsigned int interval,
  783. unsigned int duration)
  784. {
  785. RepeatEvent *re;
  786. if (interval < 1)
  787. return NULL;
  788. re = (RepeatEvent *)calloc(1, sizeof(RepeatEvent));
  789. re->re_interval = interval;
  790. re->re_duration = duration;
  791. re->re_type = RT_MINUTE;
  792. return re;
  793. }
  794. /*
  795. * Create a RepeatEvent for the daily portion of a rule.
  796. */
  797. static RepeatEvent *
  798. DeriveDailyEvent(
  799. unsigned int interval,
  800. NumberList *time_list,
  801. unsigned int duration,
  802. RepeatEvent *other_event)
  803. {
  804. RepeatEvent *re;
  805. DailyData *dd;
  806. dd = (DailyData *)calloc(1, sizeof(DailyData));
  807. /* Convert from list to array, sort */
  808. dd->dd_time = (Time *)ConvertNumList(time_list, &(dd->dd_ntime));
  809. if (interval < 1) {
  810. free(dd);
  811. return NULL;
  812. }
  813. re = (RepeatEvent *)calloc(1, sizeof(RepeatEvent));
  814. re->re_interval = interval;
  815. re->re_duration = duration;
  816. re->re_type = RT_DAILY;
  817. re->re_data.re_daily = dd;
  818. /* If there is a minuteEvent, tack it on */
  819. if (other_event) {
  820. re->re_next = other_event;
  821. other_event->re_prev = re;
  822. }
  823. return re;
  824. }
  825. /*
  826. * Create a RepeatEvent for the weekly portion of a rule.
  827. */
  828. static RepeatEvent *
  829. DeriveWeeklyEvent(
  830. unsigned int interval,
  831. DayTimeList *dtl,
  832. unsigned int duration,
  833. RepeatEvent *other_event)
  834. {
  835. RepeatEvent *re;
  836. WeeklyData *wd;
  837. wd = (WeeklyData *)calloc(1, sizeof(WeeklyData));
  838. /* Convert from list to array, sort */
  839. wd->wd_daytime = ConvertDayTime(dtl, &(wd->wd_ndaytime));
  840. if (interval < 1) {
  841. free(wd);
  842. return NULL;
  843. }
  844. re = (RepeatEvent *)calloc(1, sizeof(RepeatEvent));
  845. re->re_interval = interval;
  846. re->re_duration = duration;
  847. re->re_type = RT_WEEKLY;
  848. re->re_data.re_weekly = wd;
  849. if (other_event) {
  850. re->re_next = other_event;
  851. other_event->re_prev = re;
  852. }
  853. return re;
  854. }
  855. /*
  856. * Create a RepeatEvent for the monthly portion of a rule.
  857. */
  858. static RepeatEvent *
  859. DeriveMonthlyEvent(
  860. RepeatType type,
  861. unsigned int interval,
  862. void *data_list,
  863. unsigned int duration,
  864. RepeatEvent *other_event)
  865. {
  866. RepeatEvent *re;
  867. MonthlyData *md;
  868. md = (MonthlyData *)calloc(1, sizeof(MonthlyData));
  869. /* Convert from list to array, sort */
  870. if (type == RT_MONTHLY_POSITION) {
  871. md->md_weektime = ConvertWeekDayTime(
  872. (WeekDayTimeList *)data_list, &(md->md_nitems));
  873. } else {
  874. md->md_days = ConvertNumList(
  875. (NumberList *)data_list, &(md->md_nitems));
  876. }
  877. if (interval < 1) {
  878. free(md);
  879. return NULL;
  880. }
  881. re = (RepeatEvent *)calloc(1, sizeof(RepeatEvent));
  882. re->re_interval = interval;
  883. re->re_duration = duration;
  884. re->re_type = type;
  885. re->re_data.re_monthly = md;
  886. /* If there is an another event, tack it on */
  887. if (other_event) {
  888. re->re_next = other_event;
  889. other_event->re_prev = re;
  890. }
  891. return re;
  892. }
  893. /*
  894. * Create a RepeatEvent for the yearly portion of a rule.
  895. */
  896. static RepeatEvent *
  897. DeriveYearlyEvent(
  898. RepeatType type,
  899. unsigned int interval,
  900. NumberList *nl,
  901. unsigned int duration,
  902. RepeatEvent *other_event)
  903. {
  904. RepeatEvent *re;
  905. YearlyData *yd;
  906. yd = (YearlyData *)calloc(1, sizeof(YearlyData));
  907. /* Convert from list to array, sort */
  908. yd->yd_items = ConvertNumList(nl, &(yd->yd_nitems));
  909. if (interval < 1) {
  910. free(yd);
  911. return NULL;
  912. }
  913. re = (RepeatEvent *)calloc(1, sizeof(RepeatEvent));
  914. re->re_interval = interval;
  915. re->re_duration = duration;
  916. re->re_type = type;
  917. re->re_data.re_yearly = yd;
  918. /* If there is an another event, tack it on */
  919. if (other_event) {
  920. re->re_next = other_event;
  921. other_event->re_prev = re;
  922. }
  923. return re;
  924. }
  925. void
  926. yyerror(
  927. char *str)
  928. {
  929. /* Don't do anything */
  930. }