home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2058 / db.c next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  9.3 KB  |  463 lines

  1. /*
  2.  *    db.c : Database routines for xkal.
  3.  *           Handles searching and updating the appointment array.
  4.  *
  5.  *    George Ferguson (ferguson@cs.rochester.edu), 27 Oct 1990.
  6.  *
  7.  *    $Id: db.c,v 1.5 90/11/07 11:22:44 ferguson Exp $
  8.  *
  9.  */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13. #include <errno.h>
  14. #include <X11/Intrinsic.h>
  15. #include "util.h"
  16. #include "date-strings.h"
  17. extern char *getenv();
  18.  
  19. extern char *program;
  20.  
  21. /*
  22.  * Functions defined here:
  23.  */
  24. void initDb(), addAppoint(), deleteAppoint();
  25. void addScheduleDow(), addSchedule(), deleteScheduleDow(), deleteSchedule();
  26. char *lookup(),*lookupAppoint(),*lookupScheduleDow(),*lookupSchedule();
  27. void readAppoints(), writeAppoints();
  28. static void parseApp(), parseSched();
  29. static char *expandFilename();
  30.  
  31. /*    -    -    -    -    -    -    -    -    */
  32.  
  33. typedef struct _msgrec {
  34.     int pos;
  35.     char *text;
  36.     struct _msgrec *next;
  37. } Msgrec;
  38. typedef struct _dayrec {
  39.     int day;
  40.     Msgrec *msgs;
  41.     struct _dayrec *next;
  42. } Dayrec;
  43. typedef struct _monrec {
  44.     int mon;
  45.     Dayrec *days;
  46.     struct _monrec *next;
  47. } Monrec;
  48. typedef struct _yearrec {
  49.     int year;
  50.     Monrec *mons;
  51.     struct _yearrec *next;
  52. } Yearrec;
  53.  
  54. static Yearrec *Db = NULL;
  55. static char *schedule[7][22];
  56.  
  57. /*    -    -    -    -    -    -    -    -    */
  58. /* Initialization (pretty lame) */
  59.  
  60. void
  61. initDb()
  62. {
  63.     int i,j;
  64.  
  65.     Db = NULL;    /* should really free everything... */
  66.     for (i=0; i < 7; i++)
  67.     for (j=0; j < 22; j++)
  68.         schedule[i][j] = NULL;
  69. }
  70.  
  71. /*    -    -    -    -    -    -    -    -    */
  72. /* Appointment routines */
  73.  
  74. void
  75. addAppoint(pos,day,mon,year,text)
  76. int pos,day,mon,year;
  77. char *text;
  78. {
  79.   Yearrec *yp;
  80.   Monrec *mp;
  81.   Dayrec *dp;
  82.   Msgrec *xp;
  83.  
  84.     if (Db == NULL) {
  85.     Db = XtNew(Yearrec);
  86.     Db->year = year;
  87.     Db->mons = NULL;
  88.     Db->next = NULL;
  89.     }
  90.     for (yp = Db; yp->year != year && yp->next != NULL; yp = yp->next) ;
  91.     if (yp->year != year) {
  92.     yp->next = XtNew(Yearrec);
  93.     yp->next->year = year;
  94.     yp->next->mons = NULL;
  95.     yp->next->next = NULL;
  96.     yp = yp->next;
  97.     }
  98.     if (yp->mons == NULL) {
  99.     yp->mons = XtNew(Monrec);
  100.     yp->mons->mon = mon;
  101.     yp->mons->days = NULL;
  102.     yp->mons->next = NULL;
  103.     }
  104.     for (mp = yp->mons; mp->mon != mon && mp->next != NULL; mp = mp->next) ;
  105.     if (mp->mon != mon) {
  106.     mp->next = XtNew(Monrec);
  107.     mp->next->mon = mon;
  108.     mp->next->days = NULL;
  109.     mp->next->next=NULL;
  110.     mp = mp->next;
  111.     }
  112.  
  113.     if (mp->days == NULL) {
  114.     mp->days = XtNew(Dayrec);
  115.     mp->days->day = day;
  116.     mp->days->msgs = NULL;
  117.     mp->days->next = NULL;
  118.     }
  119.     for (dp = mp->days; dp->day != day && dp->next != NULL; dp = dp->next) ;
  120.     if (dp->day != day) {
  121.     dp->next = XtNew(Dayrec);
  122.     dp->next->day = day;
  123.     dp->next->msgs = NULL;
  124.     dp->next->next=NULL;
  125.     dp = dp->next;
  126.     }
  127.  
  128.     if (dp->msgs == NULL) {
  129.     dp->msgs = XtNew(Msgrec);
  130.     dp->msgs->pos = pos;
  131.     dp->msgs->text = NULL;
  132.     dp->msgs->next = NULL;
  133.     }
  134.     for (xp = dp->msgs; xp->pos != pos && xp->next != NULL; xp = xp->next) ;
  135.     if (xp->pos != pos) {
  136.     xp->next = XtNew(Msgrec);
  137.     xp->next->pos = pos;
  138.     xp->next->text = NULL;
  139.     xp->next->next = NULL;
  140.     xp = xp->next;
  141.     }
  142.     XtFree(xp->text);
  143.     xp->text = XtNewString(text);
  144. }
  145.  
  146. void
  147. deleteAppoint(pos,day,mon,year)
  148. int pos,day,mon,year;
  149. {
  150.   Yearrec *yp,*yp2;
  151.   Monrec *mp,*mp2;
  152.   Dayrec *dp,*dp2;
  153.   Msgrec *xp,*xp2;
  154.  
  155.     for (yp = Db; yp != NULL && yp->year != year; yp = yp->next) ;
  156.     if (yp == NULL)
  157.     return;        /* error? */
  158.  
  159.     for (mp = yp->mons; mp != NULL && mp->mon != mon; mp = mp->next) ;
  160.     if (mp == NULL)
  161.     return;        /* error? */
  162.  
  163.     for (dp = mp->days; dp != NULL && dp->day != day; dp = dp->next) ;
  164.     if (dp == NULL)
  165.     return;        /* error? */
  166.  
  167.     for (xp = dp->msgs; xp != NULL && xp->pos != pos; xp = xp->next) ;
  168.     if (xp == NULL)
  169.     return;        /* error? */
  170.  
  171.     /* Now free 'em up */
  172.  
  173.     XtFree(xp->text);        /* free the text */
  174.     
  175.     if (dp->msgs == xp)        /* and the msgrec */
  176.     dp->msgs = xp->next;
  177.     else {
  178.     for (xp2 = dp->msgs; xp2->next != xp; xp2 = xp2->next) ;
  179.     xp2->next = xp->next;
  180.     }
  181.     XtFree(xp);
  182.  
  183.     if (dp->msgs == NULL) {    /* if no more entries, free the day */
  184.     if (mp->days == dp)
  185.         mp->days = dp->next;
  186.     else {
  187.         for (dp2 = mp->days; dp2->next != dp; dp2 = dp2->next) ;
  188.         dp2->next = dp->next;
  189.     }
  190.     XtFree(dp);
  191.     }
  192.  
  193.     if (mp->days == NULL) {    /* if no more days, free the month */
  194.     if (yp->mons == mp)
  195.         yp->mons = mp->next;
  196.     else {
  197.         for (mp2 = yp->mons; mp2->next != mp; mp2 = mp2->next) ;
  198.         mp2->next = mp->next;
  199.     }
  200.     XtFree(mp);
  201.     }
  202.  
  203.     if (yp->mons == NULL) {    /* if no more months, free the year */
  204.     if (Db == yp)
  205.         Db = NULL;
  206.     else {
  207.         for (yp2 = Db; yp2->next != yp; yp2 = yp2->next) ;
  208.         yp2->next = yp->next;
  209.     }
  210.     XtFree(yp);
  211.     }
  212. }
  213.  
  214. /*    -    -    -    -    -    -    -    -    */
  215. /* Schedule routines */
  216.  
  217. void
  218. addScheduleDow(pos,dow,msg)
  219. int pos,dow;
  220. char *msg;
  221. {
  222.     XtFree(schedule[dow][pos]);
  223.     schedule[dow][pos] = XtNewString(msg);
  224. }
  225.  
  226. void
  227. addSchedule(pos,day,mon,year,msg)
  228. int pos,day,mon,year;
  229. char *msg;
  230. {
  231.     lookupScheduleDow(pos,computeDOW(day,mon,year),msg);
  232. }
  233.  
  234. void
  235. deleteScheduleDow(pos,dow)
  236. int pos,dow;
  237. {
  238.     XtFree(schedule[dow][pos]);
  239.     schedule[dow][pos] = NULL;
  240. }
  241.  
  242. void
  243. deleteSchedule(pos,day,mon,year)
  244. int pos,day,mon,year;
  245. {
  246.     lookupScheduleDow(pos,computeDOW(day,mon,year));
  247. }
  248.  
  249. /*    -    -    -    -    -    -    -    -    */
  250. /* Lookup routines */
  251.  
  252. char *
  253. lookup(pos,day,mon,year)
  254. {
  255.     char *s;
  256.  
  257.     if ((s=lookupAppoint(pos,day,mon,year)) != NULL)
  258.     return(s);
  259.     else
  260.     return(lookupSchedule(pos,day,mon,year));
  261. }
  262.  
  263. char *
  264. lookupAppoint(pos,day,mon,year)
  265. int pos,day,mon,year;
  266. {
  267.     Yearrec *yp;
  268.     Monrec *mp;
  269.     Dayrec *dp;
  270.     Msgrec *xp;
  271.  
  272.     for (yp = Db; yp != NULL && yp->year != year; yp = yp->next) ;
  273.     if (yp != NULL) {
  274.       for (mp = yp->mons; mp != NULL && mp->mon != mon; mp = mp->next) ;
  275.       if (mp != NULL) {
  276.     for (dp = mp->days; dp != NULL && dp->day != day; dp = dp->next) ;
  277.     if (dp != NULL) {
  278.       for (xp = dp->msgs; xp != NULL && xp->pos != pos; xp = xp->next) ;
  279.       if (xp != NULL)
  280.           return(xp->text);
  281.     }
  282.       }
  283.     }
  284.     return(NULL);
  285. }
  286.  
  287. char *
  288. lookupScheduleDow(pos,dow)
  289. int pos,dow;
  290. {
  291.     return(schedule[dow][pos]);
  292. }
  293.  
  294. char *
  295. lookupSchedule(pos,day,mon,year)
  296. int pos,day,mon,year;
  297. {
  298.     return(lookupScheduleDow(pos,computeDOW(day,mon,year)));
  299. }
  300.     
  301.     
  302. /*    -    -    -    -    -    -    -    -    */
  303. /* I/O routines */
  304.  
  305. void
  306. readAppoints(name)
  307. char *name;
  308. {
  309.     FILE *fp;
  310.     char *fname,buf[256];
  311.     int line,i,n,c;
  312.  
  313.     fname = expandFilename(name);
  314.     if ((fp=fopen(fname,"r")) == NULL) {
  315.     if (errno != ENOENT)    /* appointment file may not exist */
  316.         perror(fname);
  317.     return;
  318.     }
  319.     line = 0;
  320.     while (1) {
  321.     n = 0;
  322.     line += 1;
  323.     while (n < 255 && (c=getc(fp)) != EOF && c != '\n')
  324.         buf[n++] = c;
  325.     buf[n] = '\0';
  326.     if (n == 0)
  327.         break;
  328.     else if (c != EOF && c != '\n') {
  329.         fprintf(stderr,"%s: line %d too long, file %s\n",program,
  330.                                 line,fname);
  331.         while ((c=getc(fp)) != EOF && c != '\n') ;
  332.     }
  333.     for (i=0; isspace(buf[i]) && i < n; i++) ;
  334.     if (buf[i] == '#')
  335.         continue;
  336.     else if (isdigit(buf[i]))
  337.         parseApp(buf,line,fname);
  338.     else
  339.         parseSched(buf,line,fname);
  340.     }
  341.     fclose(fp);
  342. }
  343.  
  344. static void
  345. parseApp(buf,line,fname)
  346. char *buf;
  347. int line;
  348. char *fname;
  349. {
  350.     int d,m,y,h,h2,pos;
  351.     char mstr[4],msg[256];
  352.  
  353.     if (sscanf(buf,"%d %3s %d %d:%d %256[^\n]",&d,mstr,&y,&h,&h2,msg) != 6) {
  354.     fprintf(stderr,"%s: file \"%s\", line %d: invalid appointment: %s\n",
  355.                             program,fname,line,buf);
  356.     return;
  357.     }
  358.     if (islower(mstr[0]))
  359.     mstr[0] = toupper(mstr[0]);
  360.     for (m=0; m < 12; m++)
  361.     if (strncmp(shortMonStr[m],mstr,3) == 0)
  362.         break;
  363.     if (m == 12) {
  364.     fprintf(stderr,"%s: file \"%s\", line %d: invalid month: %s\n",
  365.                         program,fname,line,mstr);
  366.     return;
  367.     }
  368.     if (h2 < 30)
  369.     pos = (h-8)*2;
  370.     else
  371.     pos = (h-8)*2+1;
  372.     addAppoint(pos,d,m,y-1900,msg);
  373. }
  374.  
  375. static void
  376. parseSched(buf,line,fname)
  377. char *buf;
  378. int line;
  379. char *fname;
  380. {
  381.     int d,h,h2,pos;
  382.     char dowstr[4],msg[256];
  383.  
  384.     if (sscanf(buf,"%3s %d:%d %256[^\n]",dowstr,&h,&h2,msg) != 4) {
  385.     fprintf(stderr,"%s: file \"%s\", line %d: invalid schedule entry: %s\n",
  386.                             program,fname,line,buf);
  387.     return;
  388.     }
  389.     if (islower(dowstr[0]))
  390.     dowstr[0] = toupper(dowstr[0]);
  391.     for (d=0; d<7; d++)
  392.     if (strcmp(dowstr,shortDayStr[d]) == 0)
  393.         break;
  394.     if (d == 7) {
  395.     fprintf(stderr,"%s: file \"%s\", line %d: invalid day-of-week: %s\n",
  396.                         program,fname,line,dowstr);
  397.     return;
  398.     }
  399.     if (h2 < 30)
  400.     pos = (h-8)*2;
  401.     else
  402.     pos = (h-8)*2+1;
  403.     addScheduleDow(pos,d,msg);
  404. }
  405.  
  406. void
  407. writeAppoints(name)
  408. char *name;
  409. {
  410.     FILE *fp;
  411.     char *fname;
  412.     Yearrec *yp;
  413.     Monrec *mp;
  414.     Dayrec *dp;
  415.     Msgrec *xp;
  416.     int h,h2,i,d;
  417.  
  418.     fname = expandFilename(name);
  419.     if ((fp=fopen(fname,"w")) == NULL) {
  420.     perror(fname);
  421.     return;
  422.     }
  423.     for (d=0; d < 7; d++)
  424.     for (i=0; i < 22; i++)
  425.         if (schedule[d][i] != NULL)
  426.         fprintf(fp,"%3s %2d:%02d %s\n",shortDayStr[d],i/2+8,i%2*30,
  427.                                 schedule[d][i]);
  428.     for (yp = Db; yp != NULL; yp = yp->next)
  429.     for (mp = yp->mons; mp != NULL; mp = mp->next)
  430.         for (dp = mp->days; dp != NULL; dp = dp->next)
  431.         for (xp = dp->msgs; xp != NULL; xp = xp->next) {
  432.             h = 8+(xp->pos / 2);
  433.             h2 = (xp->pos % 2)*30;
  434.             fprintf(fp,"%2d %3.3s %4d %2d:%02d %s\n",
  435.                         dp->day,shortMonStr[mp->mon],
  436.                                 1900+yp->year,
  437.                                 h,h2,xp->text);
  438.         }
  439.     fclose(fp);
  440. }
  441.  
  442. static char filename[1024];
  443.  
  444. static char *
  445. expandFilename(name)
  446. char *name;
  447. {
  448.     char *s;
  449.  
  450.     if (*name == '~') {
  451.     if ((s=getenv("HOME")) == NULL) {
  452.         printf("%s: can't expand ~ to $HOME\n",program);
  453.         return;
  454.     } else {
  455.         strcpy(filename,s);
  456.         strcat(filename,name+1);
  457.     }
  458.     } else {
  459.     strcpy(filename,name);
  460.     }
  461.     return(filename);
  462. }
  463.