persist.cc

00001 /* persist -- Persistent Storage Management
00002    Copyright 2001, 2002 Free Software Foundation, Inc.
00003    Written by Stephane Carrez (stcarrez@nerim.fr)
00004 
00005 This file is part of GEL.
00006 
00007 GEL is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2, or (at your option)
00010 any later version.
00011 
00012 GEL is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with GEL; see the file COPYING.  If not, write to
00019 the Free Software Foundation, 59 Temple Place - Suite 330,
00020 Boston, MA 02111-1307, USA.  */
00021 
00033 #include "persist.h"
00034 #include <sys/sio.h>
00035 #include <stdarg.h>
00036 #include <time.h>
00037 #include <stdio.h>
00038 
00039 inline void
00040 print (const char* msg)
00041 {
00042   serial_print (msg);
00043 }
00044 
00045 typedef char country[20];
00046 typedef char name[12];
00047 typedef char address[32];
00048 typedef char buf[64];
00049 
00050 typedef union
00051 {
00052   name u_name;
00053   address u_address;
00054   country u_country;
00055   buf u_buf;
00056 } u_str;
00057 
00058 typedef persistent<char> p_char_t;
00059 typedef persistent<short> p_short_t;
00060 typedef persistent<long> p_long_t;
00061 typedef persistent<name> p_name_t;
00062 typedef persistent<country> p_country_t;
00063 typedef persistent<address> p_address_t;
00064 
00065 typedef enum
00066 {
00067   P_NAME,
00068   P_FIRSTNAME,
00069   P_ADDRESS,
00070   P_COUNTRY,
00071   P_NUM,
00072   P_AGE,
00073   P_UPDATE_COUNT
00074 } pids_t;
00075 
00076 volatile char __counter;
00077 
00078 void*
00079 operator new (size_t len)
00080 {
00081   printf ("new called");
00082   return 0;
00083 }
00084 
00085 void
00086 operator delete (void *ptr)
00087 {
00088   ;
00089 }
00090 
00091 void
00092 print_array (const char *p, size_t len)
00093 {
00094   while (*p && len)
00095     {
00096       printf ("%c", *p++);
00097       len--;
00098     }
00099 }
00100 
00101 void
00102 print_id ()
00103 {
00104   p_name_t p_name (P_NAME);
00105   p_name_t p_first_name (P_FIRSTNAME);
00106 
00107   printf ("\nHello ");
00108   print_array (p_first_name, sizeof (name));
00109   printf (" ");
00110   print_array (p_name, sizeof (name));
00111   printf ("!\n");
00112 }
00113 
00114 typedef enum
00115 {
00116   OP_NAME,
00117   OP_FIRSTNAME,
00118   OP_ADDRESS,
00119   OP_COUNTRY,
00120   OP_NUM,
00121   OP_AGE,
00122   OP_QUIT,
00123   OP_LIST,
00124   OP_HELP
00125 };
00126 
00127 typedef struct command
00128 {
00129   const char *name;
00130   int type;
00131   const char *help;
00132 } command;
00133 
00134 /* List of commands with a description string. */
00135 static const command commands[] = {
00136   {
00137     "name",
00138     OP_NAME,
00139     "Set the name"
00140   } , {
00141     "firstname",
00142     OP_FIRSTNAME,
00143     "Set the first name"
00144   } , {
00145     "address",
00146     OP_ADDRESS,
00147     "Set the address"
00148   } , {    
00149     "country",
00150     OP_COUNTRY,
00151     "Set the country"
00152   } , {
00153     "Number",
00154     OP_NUM,
00155     "Set the number"
00156   } , {
00157     "Age",
00158     OP_AGE,
00159     "Set the age"
00160   } , {
00161     "quit",
00162     OP_QUIT,
00163     "Quit the calculator"
00164   } , {
00165     "print",
00166     OP_LIST,
00167     "Print the information"
00168   } , {
00169     "help",
00170     OP_HELP,
00171     "This help"
00172   } , {
00173     0,
00174     0,
00175     0
00176   }
00177 };
00178 
00179 
00180 /* Implementation of some libc methods. */
00181 int
00182 strcmp (const char* s1, const char* s2)
00183 {
00184   while (*s1 && (*s1 == *s2))
00185     s1++, s2++;
00186 
00187   return *s1 - *s2;
00188 }
00189 
00190 /* Try to translate a string into a number. We look first for hexadecimal
00191    format, octal and then decimal. If the string could be converted, the
00192    value is returned in `v' and the function returns 0. Otherwise, it
00193    returns -1. */
00194 int
00195 get_value(const char* buf, long* v)
00196 {
00197   long value = 0;
00198   char c;
00199   
00200   if (!(*buf >= '0' && *buf <= '9'))
00201     return -1;
00202 
00203   /* Translate an hexadecimal value. */
00204   if (*buf == '0' && (buf[1] == 'x' || buf[1] == 'X'))
00205     {
00206       buf += 2;
00207       while ((c = *buf++))
00208         {
00209           if (c >= '0' && c <= '9')
00210             c = c - '0';
00211           else if (c >= 'a' && c <= 'f')
00212             c = c - 'a' + 10;
00213           else if (c >= 'A' && c <= 'F')
00214             c = c - 'A' + 10;
00215           else
00216             return -1;
00217 
00218           value = (value << 4) | (long) ((unsigned) c);
00219         }
00220       *v = value;
00221       return 0;
00222     }
00223   else
00224     {
00225       int sign = 0;
00226 
00227       if (buf[0] == '-')
00228         {
00229           sign = 1;
00230           buf++;
00231         }
00232       while ((c = *buf++) != 0)
00233         {
00234           if (c >= '0' && c <= '9')
00235             c = c - '0';
00236           else
00237             return -1;
00238 
00239           value = (value * 10) + (long) c;
00240         }
00241       if (sign)
00242         value = -value;
00243       *v = value;
00244       return 0;
00245     }
00246   return -1;
00247 }
00248 
00249 /* Busy loop to wait for a command or a valid number. */
00250 void
00251 cmd_get_string (char *buf)
00252 {
00253   int pos;
00254   char c;
00255 
00256   while (1)
00257     {
00258       pos = 0;
00259       while (1)
00260         {
00261           c = serial_recv ();
00262           if (c == '\r' || c == '\n')
00263             break;
00264 
00265           if (c == '\b')
00266             {
00267               printf ("\b \b");
00268               pos--;
00269               if (pos < 0)
00270                 pos = 0;
00271             }
00272           else
00273             {
00274               buf[pos] = c;
00275               buf[pos+1] = 0;
00276               printf (&buf[pos]);
00277               pos++;
00278             }
00279         }
00280 
00281       printf ("\n");
00282       buf[pos] = 0;
00283       break;
00284     }
00285 }
00286 
00287 static void
00288 print_help()
00289 {
00290   int i;
00291   
00292   for (i = 0; commands[i].name; i++)
00293     {
00294       if (commands[i].help == 0)
00295         continue;
00296 
00297       printf ("%s\t", commands[i].name);
00298       printf ("%s\n", commands[i].help);
00299     }
00300 }
00301 
00302 static name def_name = "Joe";
00303 static name def_first_name = "Dalton";
00304 static country def_country = "USA";
00305 static address def_address = "Citizen bank avenue, Red City";
00306 
00307 int
00308 cmd_loop()
00309 {
00310   int i;
00311   long val;
00312   u_str buf;
00313 
00314   // Build persistent objects.
00315   p_name_t p_name (P_NAME, def_name);
00316   p_name_t p_firstname (P_FIRSTNAME, def_first_name);
00317   p_address_t p_address (P_ADDRESS, def_address);
00318   p_country_t p_country (P_COUNTRY, def_country);
00319   p_long_t p_num (P_NUM, 0);
00320   p_long_t p_age (P_AGE, 0);
00321   p_long_t p_update_count (P_UPDATE_COUNT, 0);
00322 
00323   print_help ();
00324   while (1)
00325     {
00326       print_id ();
00327 
00328       cmd_get_string (buf.u_buf);
00329       for (i = 0; commands[i].name; i++)
00330         if (strcmp (commands[i].name, buf.u_buf) == 0)
00331           break;
00332 
00333       if (commands[i].name == 0)
00334         continue;
00335 
00336       if (commands[i].type == OP_QUIT)
00337         return 0;
00338       else if (commands[i].type == OP_HELP)
00339         {
00340           print_help ();
00341           continue;
00342         }
00343       else if (commands[i].type == OP_LIST)
00344         {
00345           printf ("Name           : ");
00346           print_array (p_name, sizeof (name));
00347           printf ("\nFirst name   : ");
00348           print_array (p_firstname, sizeof (name));
00349           printf ("\nAddress      : %ld, ", (long) p_num);
00350           print_array (p_address, sizeof (address));
00351           printf ("\nCountry      : ");
00352           print_array (p_country, sizeof (country));
00353           printf ("\nAge          : %ld", (long) p_age);
00354           printf ("\nUpdate count : %ld\n", (long) p_update_count);
00355           continue;
00356         }
00357       printf ("New value for %s :", (const char*) commands[i].name);
00358       cmd_get_string (buf.u_buf);
00359 
00360       switch (commands[i].type)
00361         {
00362         case OP_NAME:
00363           p_name = buf.u_name;
00364           break;
00365 
00366         case OP_FIRSTNAME:
00367           p_firstname = buf.u_name;
00368           break;
00369 
00370         case OP_ADDRESS:
00371           p_address = buf.u_address;
00372           break;
00373 
00374         case OP_COUNTRY:
00375           p_country = buf.u_country;
00376           break;
00377 
00378         case OP_NUM:
00379           if (get_value (buf.u_buf, &val) == 0)
00380             {
00381               p_num = val;
00382             }
00383           break;
00384 
00385         case OP_AGE:
00386           if (get_value (buf.u_buf, &val) == 0)
00387             {
00388               p_age = val;
00389             }
00390           break;
00391         }
00392       p_update_count++;
00393     }
00394 }
00395 
00396 int
00397 main()
00398 {
00399   serial_init ();
00400   
00401   printf ("Simple Persistence Test Program\n");
00402   cmd_loop ();
00403   return 0;
00404 }