"I am a person who works hard and plays hard."

Yuan Wei
Second Year Graduate Student Department of Computer Science
University of Virginia Charlottesville, VA 22903
Email: yw3f@cs.virginia.edu


Source Code Analysis

Main Page   Compound List   File List   Compound Members   File Members  

libexo.h File Reference

#include "../host.h"
#include "../misc.h"
#include "../machine.h"

Include dependency graph for libexo.h:

Include dependency graph

This graph shows which files directly or indirectly include this file:

Included by dependency graph

Go to the source code of this file.

Compounds

Defines

Enumerations

Functions

Variables


Define Documentation

#define as_address   variant.as_address
 

Definition at line 156 of file libexo.h.

#define as_array   variant.as_array
 

Definition at line 161 of file libexo.h.

#define as_blob   variant.as_blob
 

Definition at line 163 of file libexo.h.

#define as_char   variant.as_char
 

Definition at line 158 of file libexo.h.

#define as_float   variant.as_float
 

Definition at line 157 of file libexo.h.

#define as_integer   variant.as_integer
 

Definition at line 155 of file libexo.h.

#define as_list   variant.as_list
 

Definition at line 160 of file libexo.h.

#define as_string   variant.as_string
 

Definition at line 159 of file libexo.h.

#define as_token   variant.as_token
 

Definition at line 162 of file libexo.h.

#define EXO_ARR E,
N   
 

Value:

((E)->ec != ec_array                                                    \
   ? (fatal("not an array"), *(struct exo_term_t **)(NULL))             \
   : ((N) >= (E)->as_array.size                                         \
      ? (fatal("array bounds error"), *(struct exo_term_t **)(NULL))    \
      : (E)->as_array.array[(N)]))

Definition at line 167 of file libexo.h.

Referenced by exo_copy(), exo_deepcopy(), exo_print(), and main().

#define EXO_FMT_MAJOR   1
 

Definition at line 91 of file libexo.h.

Referenced by main().

#define EXO_FMT_MINOR   0
 

Definition at line 92 of file libexo.h.

Referenced by main().

#define SET_EXO_ARR E,
N,
 
 

Value:

((E)->ec != ec_array                                                    \
   ? (void)fatal("not an array")                                        \
   : ((N) >= (E)->as_array.size                                         \
      ? (void)fatal("array bounds error")                               \
      : (void)((E)->as_array.array[(N)] = (V))))

Definition at line 173 of file libexo.h.

Referenced by exo_copy(), exo_deepcopy(), exo_new(), and exo_read().


Enumeration Type Documentation

enum exo_class_t
 

Enumeration values:
ec_integer 
ec_address 
ec_float 
ec_char 
ec_string 
ec_list 
ec_array 
ec_token 
ec_blob 
ec_null 
ec_NUM 

Definition at line 95 of file libexo.h.

00095                  {
00096   ec_integer,                   /* EXO int value */
00097   ec_address,                   /* EXO address value */
00098   ec_float,                     /* EXO FP value */
00099   ec_char,                      /* EXO character value */
00100   ec_string,                    /* EXO string value */
00101   ec_list,                      /* EXO list */
00102   ec_array,                     /* EXO array */
00103   ec_token,                     /* EXO token value */
00104   ec_blob,                      /* EXO blob (Binary Large OBject) */
00105   ec_null,                      /* used internally */
00106   ec_NUM
00107 };

enum lex_t
 

Enumeration values:
lex_integer 
lex_address 
lex_float 
lex_char 
lex_string 
lex_token 
lex_byte 
lex_eof 

Definition at line 230 of file libexo.h.

00230            {
00231   lex_integer = 256,
00232   lex_address,
00233   lex_float,
00234   lex_char,
00235   lex_string,
00236   lex_token,
00237   lex_byte,
00238   lex_eof
00239 };


Function Documentation

struct exo_term_t* exo_chain struct exo_term_t   fore,
struct exo_term_t   aft
 

Definition at line 627 of file libexo.c.

References exo_term_t::next.

Referenced by eio_write_chkpt(), eio_write_trace(), exo_deepcopy(), exo_new(), exo_read(), main(), and my_mem_fn().

00628 {
00629   struct exo_term_t *exo, *prev;
00630 
00631   if (!fore && !aft)
00632     return NULL;
00633 
00634   if (!fore)
00635     return aft;
00636 
00637   /* find the tail of FORE */
00638   for (prev=NULL,exo=fore; exo != NULL; prev=exo,exo=exo->next)
00639     /* nada */;
00640   assert(prev);
00641 
00642   /* link onto the tail of FORE */
00643   prev->next = aft;
00644 
00645   return fore;
00646 }

struct exo_term_t* exo_copy struct exo_term_t   exo
 

Definition at line 650 of file libexo.c.

References exo_term_t::as_array, exo_term_t::as_blob, exo_term_t::ec, ec_address, ec_array, ec_blob, ec_char, ec_float, ec_integer, ec_list, ec_string, ec_token, exo_alloc(), EXO_ARR, exo_term_t::next, panic(), and SET_EXO_ARR.

Referenced by exo_deepcopy().

00651 {
00652   struct exo_term_t *new_exo;
00653 
00654   /* NULL copy */
00655   if (!exo)
00656     return NULL;
00657 
00658   new_exo = exo_alloc(exo->ec);
00659   *new_exo = *exo;
00660 
00661   /* the next link is always blown away on a copy */
00662   new_exo->next = NULL;
00663 
00664   switch (new_exo->ec)
00665     {
00666     case ec_integer:
00667     case ec_address:
00668     case ec_float:
00669     case ec_char:
00670     case ec_string:
00671     case ec_list:
00672     case ec_token:
00673       /* no internal parts to copy */
00674       break;
00675 
00676     case ec_array:
00677       {
00678         int i;
00679 
00680         /* copy the array */
00681         new_exo->as_array.array = (struct exo_term_t **)
00682           calloc(new_exo->as_array.size, sizeof(struct exo_term_t *));
00683 
00684         for (i=0; i<new_exo->as_array.size; i++)
00685           {
00686             SET_EXO_ARR(new_exo, i, EXO_ARR(exo, i));
00687           }
00688       }
00689       break;
00690 
00691     case ec_blob:
00692       new_exo->as_blob.data = malloc(new_exo->as_array.size);
00693       memcpy(new_exo->as_blob.data, exo->as_blob.data, new_exo->as_array.size);
00694       break;
00695 
00696     default:
00697       panic("bogus EXO class");
00698     }
00699 
00700   return new_exo;
00701 }

struct exo_term_t* exo_deepcopy struct exo_term_t   exo
 

Definition at line 705 of file libexo.c.

References exo_term_t::as_array, exo_term_t::as_blob, exo_term_t::as_list, exo_term_t::as_string, exo_term_t::ec, ec_address, ec_array, ec_blob, ec_char, ec_float, ec_integer, ec_list, ec_string, ec_token, EXO_ARR, exo_chain(), exo_copy(), mystrdup(), exo_term_t::next, panic(), and SET_EXO_ARR.

Referenced by main().

00706 {
00707   struct exo_term_t *new_exo;
00708 
00709   /* NULL copy */
00710   if (!exo)
00711     return NULL;
00712 
00713   new_exo = exo_copy(exo);
00714   switch (new_exo->ec)
00715     {
00716     case ec_integer:
00717     case ec_address:
00718     case ec_float:
00719     case ec_char:
00720     case ec_token:
00721       /* exo_copy() == exo_deepcopy() for these node classes */
00722       break;
00723 
00724     case ec_string:
00725       /* copy the referenced string */
00726       new_exo->as_string.str =
00727         (unsigned char *)mystrdup((char *)exo->as_string.str);
00728       break;
00729 
00730     case ec_list:
00731       /* copy all list elements */
00732       {
00733         struct exo_term_t *elt, *new_elt, *new_list;
00734 
00735         new_list = NULL;
00736         for (elt=new_exo->as_list.head; elt != NULL; elt=elt->next)
00737           {
00738             new_elt = exo_deepcopy(elt);
00739             new_list = exo_chain(new_list, new_elt);
00740           }
00741         new_exo->as_list.head = new_list;
00742       }
00743       break;
00744 
00745     case ec_array:
00746       /* copy all array elements */
00747       {
00748         int i;
00749 
00750         for (i=0; i<new_exo->as_array.size; i++)
00751           {
00752             SET_EXO_ARR(new_exo, i, exo_deepcopy(EXO_ARR(exo, i)));
00753           }
00754       }
00755       break;
00756 
00757     case ec_blob:
00758       new_exo->as_blob.data = malloc(new_exo->as_array.size);
00759       memcpy(new_exo->as_blob.data, exo->as_blob.data, new_exo->as_array.size);
00760       break;
00761 
00762     default:
00763       panic("bogus EXO class");
00764     }
00765 
00766   return new_exo;
00767 }

void exo_delete struct exo_term_t   exo
 

Definition at line 542 of file libexo.c.

References exo_term_t::as_address, exo_term_t::as_array, exo_term_t::as_blob, exo_term_t::as_char, exo_term_t::as_float, exo_term_t::as_integer, exo_term_t::as_list, exo_term_t::as_string, exo_term_t::as_token, exo_term_t::ec, ec_address, ec_array, ec_blob, ec_char, ec_float, ec_integer, ec_list, ec_null, ec_string, ec_token, exo_term_t::next, and panic().

Referenced by eio_create(), eio_open(), eio_read_chkpt(), eio_read_trace(), eio_write_chkpt(), eio_write_trace(), and exo_read().

00543 {
00544   exo->next = NULL;
00545 
00546   switch (exo->ec)
00547     {
00548     case ec_integer:
00549       /* no extra storage */
00550       exo->as_integer.val = 0;
00551       break;
00552 
00553     case ec_address:
00554       /* no extra storage */
00555       exo->as_address.val = 0;
00556       break;
00557 
00558     case ec_float:
00559       /* no extra storage */
00560       exo->as_float.val = 0.0;
00561       break;
00562 
00563     case ec_char:
00564       /* no extra storage */
00565       exo->as_char.val = '\0';
00566       break;
00567 
00568     case ec_string:
00569       free(exo->as_string.str);
00570       exo->as_string.str = NULL;
00571       break;
00572 
00573     case ec_list:
00574       {
00575         struct exo_term_t *ent, *next_ent;
00576 
00577         for (ent=exo->as_list.head; ent != NULL; ent = next_ent)
00578           {
00579             next_ent = ent->next;
00580             exo_delete(ent);
00581           }
00582         exo->as_list.head = NULL;
00583       }
00584       break;
00585 
00586     case ec_array:
00587       {
00588         int i;
00589 
00590         for (i=0; i < exo->as_array.size; i++)
00591           {
00592             if (exo->as_array.array[i] != NULL)
00593               exo_delete(exo->as_array.array[i]);
00594           }
00595         free(exo->as_array.array);
00596         exo->as_array.array = NULL;
00597         exo->as_array.size = 0;
00598       }
00599       break;
00600 
00601     case ec_token:
00602       /* no extra storage */
00603       exo->as_token.ent = NULL;
00604       break;
00605 
00606     case ec_blob:
00607       /* free the blob data */
00608       free(exo->as_blob.data);
00609       exo->as_blob.data = NULL;
00610       break;
00611 
00612     case ec_null:
00613       /* no extra storage */
00614       break;
00615 
00616     default:
00617       panic("bogus EXO class");
00618     }
00619   exo->ec = (enum exo_class_t)0;
00620 
00621   /* release the node */
00622   free(exo);
00623 }

struct exo_token_t* exo_intern char *    token_str
 

Definition at line 351 of file libexo.c.

References fatal(), hash_str(), mystrdup(), exo_token_t::next, exo_token_t::str, exo_token_t::token, and token_id.

Referenced by exo_intern_as(), and exo_new().

00352 {
00353   int index;
00354   struct exo_token_t *ent;
00355 
00356   index = hash_str(token_str);
00357 
00358   for (ent=token_hash[index]; ent != NULL; ent=ent->next)
00359     {
00360       if (!strcmp(token_str, ent->str))
00361         {
00362           /* got a match, return token entry */
00363           return ent;
00364         }
00365     }
00366 
00367   /* not found, create a new entry */
00368   ent = (struct exo_token_t *)calloc(1, sizeof(struct exo_token_t));
00369   if (!ent)
00370     fatal("out of virtual memory");
00371 
00372   ent->str = mystrdup(token_str);
00373   ent->token = token_id++;
00374   ent->next = token_hash[index];
00375   token_hash[index] = ent;
00376 
00377   return ent;
00378 }

struct exo_token_t* exo_intern_as char *    token_str,
int    token
 

Definition at line 382 of file libexo.c.

References exo_intern(), fatal(), exo_token_t::token, and token_id.

Referenced by main().

00384 {
00385   struct exo_token_t *ent;
00386 
00387 #if 0
00388   if (token_id > token)
00389     fatal("token value is already in use");
00390 #endif
00391 
00392   ent = exo_intern(token_str);
00393   /* overide the default value */
00394   ent->token = token;
00395 
00396 #if 0
00397   if (ent->token != token)
00398     fatal("symbol `%s' was previously interned", token_str);
00399 #endif
00400 
00401   return ent;
00402 }

struct exo_term_t* exo_new enum exo_class_t    ec,
...   
 

Definition at line 433 of file libexo.c.

References exo_term_t::as_address, exo_term_t::as_array, exo_term_t::as_blob, exo_term_t::as_char, exo_term_t::as_float, exo_term_t::as_integer, exo_term_t::as_list, exo_term_t::as_string, exo_term_t::as_token, exo_term_t::data, ec_address, ec_array, ec_blob, ec_char, ec_float, ec_integer, ec_list, ec_null, ec_string, ec_token, exo_alloc(), exo_chain(), exo_intern(), fatal(), mystrdup(), panic(), SET_EXO_ARR, exo_term_t::size, and exo_term_t::str.

Referenced by eio_create(), eio_write_chkpt(), eio_write_trace(), exo_read(), main(), and my_mem_fn().

00434 {
00435   struct exo_term_t *exo;
00436   va_list v;
00437   va_start(v, ec);
00438 
00439   exo = exo_alloc(ec);
00440   switch (ec)
00441     {
00442     case ec_integer:
00443       exo->as_integer.val = va_arg(v, exo_integer_t);
00444       break;
00445 
00446     case ec_address:
00447       exo->as_address.val = va_arg(v, exo_address_t);
00448       break;
00449 
00450     case ec_float:
00451       exo->as_float.val = va_arg(v, exo_float_t);
00452       break;
00453 
00454     case ec_char:
00455       exo->as_char.val = va_arg(v, int);
00456       break;
00457 
00458     case ec_string:
00459       {
00460         char *str;
00461 
00462         str = va_arg(v, char *);
00463         exo->as_string.str = (unsigned char *)mystrdup(str);
00464       }
00465       break;
00466 
00467     case ec_list:
00468       {
00469         struct exo_term_t *ent;
00470 
00471         exo->as_list.head = NULL;
00472         do {
00473           ent = va_arg(v, struct exo_term_t *);
00474           exo->as_list.head = exo_chain(exo->as_list.head, ent);
00475         } while (ent != NULL);
00476       }
00477       break;
00478 
00479     case ec_array:
00480       {
00481         int i;
00482         struct exo_term_t *ent;
00483 
00484         exo->as_array.size = va_arg(v, int);
00485         exo->as_array.array = (struct exo_term_t **)
00486           calloc(exo->as_array.size, sizeof(struct exo_term_t *));
00487         if (!exo->as_array.array)
00488           fatal("out of virtual memory");
00489         i = 0;
00490         do {
00491           ent = va_arg(v, struct exo_term_t *);
00492           if (ent != NULL)
00493             {
00494               if (i == exo->as_array.size)
00495                 fatal("array constructor overflow");
00496               SET_EXO_ARR(exo, i, ent);
00497             }
00498           i++;
00499         } while (ent != NULL);
00500       }
00501       break;
00502 
00503     case ec_token:
00504       {
00505         char *str;
00506 
00507         str = va_arg(v, char *);
00508         exo->as_token.ent = exo_intern(str);
00509       }
00510       break;
00511 
00512     case ec_blob:
00513       {
00514         unsigned size;
00515         unsigned char *data;
00516 
00517         size = va_arg(v, unsigned);
00518         data = va_arg(v, unsigned char *);
00519 
00520         exo->as_blob.size = size;
00521         exo->as_blob.data = malloc(size);
00522         if (data != NULL)
00523           memcpy(exo->as_blob.data, data, size);
00524         else
00525           memset(exo->as_blob.data, 0, size);
00526       }
00527       break;
00528 
00529     case ec_null:
00530       break;
00531 
00532     default:
00533       panic("bogus EXO class");
00534     }
00535 
00536   va_end(v);
00537   return exo;
00538 }

void exo_print struct exo_term_t   exo,
FILE *    stream
 

Definition at line 771 of file libexo.c.

References exo_term_t::as_array, exo_term_t::as_blob, exo_term_t::as_char, exo_term_t::as_float, exo_term_t::as_integer, exo_term_t::as_list, exo_term_t::as_string, exo_term_t::as_token, exo_term_t::ec, ec_address, ec_array, ec_blob, ec_char, ec_float, ec_integer, ec_list, ec_string, ec_token, EXO_ARR, FALSE, myfprintf(), exo_term_t::next, panic(), print_char(), print_string(), and TRUE.

Referenced by eio_create(), eio_write_chkpt(), eio_write_trace(), and main().

00772 {
00773   if (!stream)
00774     stream = stderr;
00775 
00776   switch (exo->ec)
00777     {
00778     case ec_integer:
00779       if (sizeof(exo_integer_t) == 4)
00780         myfprintf(stream, "%u", exo->as_integer.val);
00781       else
00782         myfprintf(stream, "%lu", exo->as_integer.val);
00783       break;
00784 
00785     case ec_address:
00786       if (sizeof(exo_address_t) == 4)
00787         myfprintf(stream, "0x%x", exo->as_integer.val);
00788       else
00789         myfprintf(stream, "0x%lx", exo->as_integer.val);
00790       break;
00791 
00792     case ec_float:
00793       fprintf(stream, "%f", exo->as_float.val);
00794       break;
00795 
00796     case ec_char:
00797       fprintf(stream, "'");
00798       print_char(exo->as_char.val, stream);
00799       fprintf(stream, "'");
00800       break;
00801 
00802     case ec_string:
00803       fprintf(stream, "\"");
00804       print_string(exo->as_string.str, stream);
00805       fprintf(stream, "\"");
00806       break;
00807 
00808     case ec_list:
00809       {
00810         struct exo_term_t *ent;
00811 
00812         fprintf(stream, "(");
00813         for (ent=exo->as_list.head; ent != NULL; ent=ent->next)
00814           {
00815             exo_print(ent, stream);
00816             if (ent->next)
00817               fprintf(stream, ", ");
00818           }
00819         fprintf(stream, ")");
00820       }
00821       break;
00822 
00823     case ec_array:
00824       {
00825         int i, last;
00826 
00827         /* search for last first non-NULL entry */
00828         for (last=exo->as_array.size-1; last >= 0; last--)
00829           {
00830             if (EXO_ARR(exo, last) != NULL)
00831               break;
00832           }
00833         /* LAST == index of last non-NULL array entry */
00834 
00835         fprintf(stream, "{%d}[", exo->as_array.size);
00836         for (i=0; i<exo->as_array.size && i <= last; i++)
00837           {
00838             if (exo->as_array.array[i] != NULL)
00839               exo_print(exo->as_array.array[i], stream);
00840             else
00841               fprintf(stream, " ");
00842             if (i != exo->as_array.size-1 && i != last)
00843               fprintf(stream, ", ");
00844           }
00845         fprintf(stream, "]");
00846       }
00847       break;
00848 
00849     case ec_token:
00850       fprintf(stream, "%s", exo->as_token.ent->str);
00851       break;
00852 
00853     case ec_blob:
00854       {
00855         int i, cr;
00856 
00857         fprintf(stream, "{%d}<\n", exo->as_blob.size);
00858         for (i=0; i < exo->as_blob.size; i++)
00859           {
00860             cr = FALSE;
00861             if (i != 0 && (i % 38) == 0)
00862               {
00863                 fprintf(stream, "\n");
00864                 cr = TRUE;
00865               }
00866             fprintf(stream, "%02x", exo->as_blob.data[i]);
00867           }
00868         if (!cr)
00869           fprintf(stream, "\n");
00870         fprintf(stream, ">");
00871       }
00872       break;
00873 
00874     default:
00875       panic("bogus EXO class");
00876     }
00877 }

struct exo_term_t* exo_read FILE *    stream
 

Definition at line 896 of file libexo.c.

References exo_term_t::as_array, exo_term_t::as_blob, exo_term_t::as_integer, exo_term_t::as_list, exo_term_t::ec, ec_address, ec_array, ec_blob, ec_char, ec_float, ec_integer, ec_list, ec_null, ec_string, ec_token, exo_chain(), exo_delete(), exo_err(), exo_new(), intern_char(), intern_string(), lex_address, lex_byte, lex_char, lex_eof, lex_float, lex_integer, lex_string, lex_token, exo_term_t::next, panic(), s, SET_EXO_ARR, exo_term_t::size, yy_nextchar(), yylex(), and yytext.

Referenced by eio_fast_forward(), eio_open(), eio_read_chkpt(), eio_read_trace(), and main().

00897 {
00898   int tok;
00899   char tok_buf[1024], *endp;
00900   struct exo_term_t *ent = NULL;
00901   extern int errno;
00902   extern void yy_setstream(FILE *);
00903 
00904   /* make sure we have a valid stream */
00905   if (!stream)
00906     stream = stdin;
00907   yy_setstream(stream);
00908 
00909   /* make local copies of everything, allows arbitrary recursion */
00910   tok = yylex();
00911   strcpy(tok_buf, yytext);
00912 
00913   switch (tok)
00914     {
00915     case lex_integer:
00916       {
00917         exo_integer_t int_val;
00918 
00919         /* attempt integer conversion */
00920         errno = 0;
00921 #ifdef HOST_HAS_QWORD
00922         int_val = myatoq(tok_buf, &endp, /* parse base */10);
00923 #else /* !HOST_HAS_QWORD */
00924         int_val = strtoul(tok_buf, &endp, /* parse base */10);
00925 #endif /* HOST_HAS_QWORD */
00926         if (!errno && !*endp)
00927           {
00928             /* good conversion */
00929             ent = exo_new(ec_integer, int_val);
00930           }
00931         else
00932           exo_err("cannot parse integer literal");
00933       }
00934       break;
00935 
00936     case lex_address:
00937       {
00938         exo_address_t addr_val;
00939 
00940         /* attempt address conversion */
00941         errno = 0;
00942 #ifdef HOST_HAS_QWORD
00943         addr_val = myatoq(tok_buf, &endp, /* parse base */16);
00944 #else /* !HOST_HAS_QWORD */
00945         addr_val = strtoul(tok_buf, &endp, /* parse base */16);
00946 #endif /* HOST_HAS_QWORD */
00947         if (!errno && !*endp)
00948           {
00949             /* good conversion */
00950             ent = exo_new(ec_address, addr_val);
00951           }
00952         else
00953           exo_err("cannot parse address literal");
00954       }
00955       break;
00956 
00957     case lex_float:
00958       {
00959         exo_float_t float_val;
00960 
00961         /* attempt double conversion */
00962         errno = 0;
00963         float_val = strtod(tok_buf, &endp);
00964         if (!errno && !*endp)
00965           {
00966             /* good conversion */
00967             ent = exo_new(ec_float, float_val);
00968           }
00969         else
00970           exo_err("cannot parse floating point literal");
00971       }
00972       break;
00973 
00974     case lex_char:
00975       {
00976         int c;
00977 
00978         c = intern_char(tok_buf, &endp);
00979         if (!endp)
00980           exo_err("cannot convert character literal");
00981         ent = exo_new(ec_char, c);
00982       }
00983       break;
00984 
00985     case lex_string:
00986       {
00987         char *s;
00988 
00989         s = intern_string(tok_buf);
00990         ent = exo_new(ec_string, s);
00991         free(s);
00992       }
00993       break;
00994 
00995     case lex_token:
00996       ent = exo_new(ec_token, tok_buf);
00997       break;
00998 
00999     case lex_byte:
01000       exo_err("unexpected blob byte encountered");
01001       break;
01002 
01003     case '(':
01004       {
01005         struct exo_term_t *elt;
01006 
01007         ent = exo_new(ec_list, NULL);
01008 
01009         if (yy_nextchar() != ')')
01010           {
01011             /* not an empty list */
01012             do {
01013               elt = exo_read(stream);
01014               if (!elt)
01015                 exo_err("unexpected end-of-file");
01016               ent->as_list.head =
01017                 exo_chain(ent->as_list.head, elt);
01018 
01019               /* consume optional commas */
01020               if (yy_nextchar() == ',')
01021                 yylex();
01022             } while (yy_nextchar() != ')');
01023           }
01024 
01025         /* read tail delimiter */
01026         tok = yylex();
01027         if (tok != ')')
01028           exo_err("expected ')'");
01029       }
01030       break;
01031 
01032     case ')':
01033       exo_err("unexpected ')' encountered");
01034       break;
01035 
01036     case '<':
01037       exo_err("unexpected '<' encountered");
01038       break;
01039 
01040     case '>':
01041       exo_err("unexpected '>' encountered");
01042       break;
01043 
01044     case '{':
01045       {
01046         int cnt, size;
01047         struct exo_term_t *elt;
01048 
01049         /* get the size */
01050         elt = exo_read(stream);
01051         if (!elt || elt->ec != ec_integer)
01052           exo_err("badly formed array size");
01053 
01054         /* record the size of the array/blob */
01055         size = (int)elt->as_integer.val;
01056 
01057         /* done with the EXO integer */
01058         exo_delete(elt);
01059 
01060         /* read the array delimiters */
01061         tok = yylex();
01062         if (tok != '}')
01063           exo_err("expected '}'");
01064 
01065         tok = yylex();
01066         switch (tok)
01067           {
01068           case '[': /* array definition */
01069             /* allocate an array definition */
01070             ent = exo_new(ec_array, size, NULL);
01071 
01072             /* read until array is full or tail delimiter encountered */
01073             if (yy_nextchar() != ']')
01074               {
01075                 /* not an empty array */
01076                 cnt = 0;
01077                 do {
01078                   if (cnt == ent->as_array.size)
01079                     exo_err("too many initializers for array");
01080 
01081                   /* NULL element? */
01082                   if (yy_nextchar() == ',')
01083                     {
01084                       elt = NULL;
01085                     }
01086                   else
01087                     {
01088                       elt = exo_read(stream);
01089                       if (!elt)
01090                         exo_err("unexpected end-of-file");
01091                     }
01092                   SET_EXO_ARR(ent, cnt, elt);
01093                   cnt++;
01094 
01095                   /* consume optional commas */
01096                   if (yy_nextchar() == ',')
01097                     yylex();
01098                 } while (yy_nextchar() != ']');
01099               }
01100 
01101             /* read tail delimiter */
01102             tok = yylex();
01103             if (tok != ']')
01104               exo_err("expected ']'");
01105             break;
01106 
01107           case '<': /* blob definition */
01108             /* allocate an array definition */
01109             ent = exo_new(ec_blob, size, /* zero contents */NULL);
01110 
01111             /* read until blob is full */
01112             if (yy_nextchar() != '>')
01113               {
01114                 unsigned int byte_val;
01115 
01116                 /* not an empty array */
01117                 cnt = 0;
01118                 for (;;) {
01119                   /* read next blob byte */
01120                   tok = yylex();
01121 
01122                   if (tok == lex_byte)
01123                     {
01124                       if (cnt == ent->as_blob.size)
01125                         exo_err("too many initializers for blob");
01126 
01127                       /* attempt hex conversion */
01128                       errno = 0;
01129                       byte_val = strtoul(yytext, &endp, /* parse base */16);
01130                       if (errno != 0 || *endp != '\0')
01131                         exo_err("cannot parse blob byte literal");
01132                       if (byte_val > 255)
01133                         panic("bogus byte value");
01134                       ent->as_blob.data[cnt] = byte_val;
01135                       cnt++;
01136                     }
01137                   else if (tok == '>')
01138                     break;
01139                   else
01140                     exo_err("unexpected character in blob");
01141                 }
01142               }
01143 
01144 #if 0 /* zero tail is OK... */
01145             if (cnt != ent->as_blob.size)
01146               exo_err("not enough initializers for blob");
01147 #endif
01148             break;
01149 
01150           default:
01151             exo_err("expected '[' or '<'");
01152           }
01153       }
01154       break;
01155 
01156     case '}':
01157       exo_err("unexpected '}' encountered");
01158       break;
01159 
01160     case ',':
01161       exo_err("unexpected ',' encountered");
01162       break;
01163 
01164     case '[':
01165       {
01166         int i, cnt;
01167         struct exo_term_t *list, *elt, *next_elt;
01168 
01169         /* compute the array size */
01170         list = NULL;
01171         if (yy_nextchar() == ']')
01172           exo_err("unsized array has no initializers");
01173 
01174         cnt = 0;
01175         do {
01176           /* NULL element? */
01177           if (yy_nextchar() == ',')
01178             {
01179               elt = exo_new(ec_null);
01180             }
01181           else
01182             {
01183               elt = exo_read(stream);
01184               if (!elt)
01185                 exo_err("unexpected end-of-file");
01186             }
01187           cnt++;
01188           list = exo_chain(list, elt);
01189 
01190           /* consume optional commas */
01191           if (yy_nextchar() == ',')
01192             yylex();
01193         } while (yy_nextchar() != ']');
01194 
01195         /* read tail delimiter */
01196         tok = yylex();
01197         if (tok != ']')
01198           exo_err("expected ']'");
01199 
01200         /* create the array */
01201         assert(cnt > 0);
01202         ent = exo_new(ec_array, cnt, NULL);
01203 
01204         /* fill up the array */
01205         for (i=0,elt=list; i<cnt; i++,elt=next_elt)
01206           {
01207             assert(elt != NULL);
01208             next_elt = elt->next;
01209             if (elt->ec == ec_null)
01210               {
01211                 SET_EXO_ARR(ent, cnt, NULL);
01212                 exo_delete(ent);
01213               }
01214             else
01215               {
01216                 SET_EXO_ARR(ent, cnt, elt);
01217                 elt->next = NULL;
01218               }
01219           }
01220       }
01221       break;
01222 
01223     case ']':
01224       exo_err("unexpected ']' encountered");
01225       break;
01226 
01227     case lex_eof:
01228       /* nothing to read */
01229       ent = NULL;
01230       break;
01231 
01232     default:
01233       panic("bogus token");
01234     }
01235 
01236   return ent;
01237 }


Variable Documentation

char* exo_class_str[ec_NUM]
 

Definition at line 110 of file libexo.h.



UVa CS Department of Computer Science
School of Engineering, University of Virginia
151 Engineer's Way, P.O. Box 400740
Charlottesville, Virginia 22904-4740

(434) 982-2200  Fax: (434) 982-2214