%{
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "kernel.h"
#include "headers.h"
#include "player.h"

extern	int		lineno;
extern	char		*yytext;

int			using_file = 0;

struct base		**cell		= NULL; /* vector of states
                                                 */
struct hash		**hash_table	= NULL; /* hashing table, points
                                                 * to the vector of states
                                                 */
int			initiated	= 0;    /* malloced ?
                                                 */
u_int32_t		next_available	= 0;    /* next ?
                                                 */
u_int32_t		number_of_states= 0;    /* total of states
                                                 */
u_int32_t		hash_size	= 0;    /* size of the hashing table, 
                                                 * should be 3x the total
                                                 * number of states
                                                 */
int32_t			current_state	= 0;    /* working state, it holds
                                                 * the state position on 
                                                 * the hashing table
	   					 */
u_int8_t		verbose		= 1;	/* Verbose ? default = yep
						 */
FILE			*output_file	= NULL; /* LOG file
                                                 */
char			y_n_answ	= 0;	/* yes/no question
						 */
u_int16_t		nof		= 0;	/* Number of fields (recv section)
						 */
u_int16_t		nob		= 0;	/* Number of branches (recv section)
						 */
u_int16_t               noh		= 0;	/* Number of headers loaded (header section)
						 */
u_int32_t		noph		= 0;	/* Number of Previous headers
						 */
u_int32_t		nobt		= 0;	/* Number of BuTs (fields to change) (send section)
						 */
u_int32_t		nosp		= 0;	/* Number of stored packets
						 */
struct rlz{
  struct field_off_bits	info;
  struct rlz		*next;
} 		*rlaux = NULL, *rules_chainl = NULL,	/* rules chain list (recv section)*/
		*rlpivot = NULL;

struct brch_in	*braux = NULL, *branches_chainl = NULL,	/* branches chain list (recv section) */
		*brpivot = NULL;				 	
struct but_in	*baux = NULL, *but_chainl = NULL,	/* but chain list (send section)*/
		*bpivot = NULL;

char			header_dir[256];	/* Headers definition directory
						 */
struct hdir_in		*hd;			/* Internal header directory structure
						 */
struct header_hash_table **head_hash;		/* Header definition hash table
						 */
struct header_info 	*finfo;			/* Information returned by gimme_the_data
						 */
char			bpf_expr[256];		/* BPF expression
						 */
char			iface[128];		/* Interface to be used
						 */
char			**pheader;		/* Previous headers vector
						 */
struct phl{
  struct phinf		*prvhinf;
  struct phl		*next;
}		*phlaux,*pheaderl = NULL;	/* Previous headers chained list
						 */
struct pack_vect	*packs2bsnt;		/* Packets to be sent structure
						 */

int16_t			debbug		= 0;	/* Debbug level
						 */
u_int16_t		aux;			/* Auxiliary variable
						 */
char			buff[256];		/* Buffer */

int			i;			/* Index variable  */

%}

%union {
  int			yyint;
  char			yychar;
  char			*yystr;
  u_int32_t		yyuint32t;
  struct yac_in		yin;
  struct timeout	s_timeout;
  struct but		but_t;
  struct but_args	but_a;
  struct field_off_bits	f_info;
}

%type   <yin>   	action
%type	<yyint>		time
%type	<s_timeout>	timeout
%type   <but_t>		but_oper
%type	<but_a>		but_data
%type	<f_info>	f_addr, b_field
%type	<yyuint32t>	f_value, f_value_expr

%token	WAIT_T RECV_PACKET_T SEND_PACKET_T FINISH_T SHELL_T
%token	PM_AND PM_OR CHAR STD_CHECKSUM VERBOSE ON OFF 
%token	BPF PACKETS OPER EQUAL IFACE
%token	OPEN_BRACK CLOSE_BRACK OPEN_BRACE CLOSE_BRACE EOL PACK_ID
%token	INIT NUMBER STR EXPR ALL USED NEXT HEADERS LOAD
%token	CREATE STATE ACTION STATES CHECK RESOLVE
%token	SHOW TERMINATE STOR_PACK PLAY
%token	M_SEC U_SEC RID TIMEOUT BUT COMMAND

%type	<yyint>		NUMBER U_SEC M_SEC
%type	<yystr>		STR EXPR
%type	<yychar>	OPER,CHAR

%%
start: expression
     ;

/* Here is initialized a hash table with 3*x addresses
 */
expression: INIT NUMBER STATES {
              if(!initiated){
		number_of_states = $2;
                hash_size = number_of_states*3;
                cell = (struct base**)malloc($2*sizeof(struct base*));
                memset(cell,0,$2*sizeof(struct base*));
                hash_table = (struct hash**)malloc($2*3*sizeof(struct hash*));
                memset(hash_table,0,$2*3*sizeof(struct hash*));
                initiated = 1;
		if(output_file == NULL)
		  output_file = stdout; 
		if(!using_file) printf("ok!\n");
              }else{
                 yyerror("Failed! Hashing table already initiated.");
               }
            }
	  | LOAD HEADERS ':' EXPR {
	      memset(header_dir,0,256);
	      memcpy(header_dir,$4,(strlen($4))%256);
	      count_headers(header_dir,&hd);
	      noh = count_noh(hd);
	      head_hash = mount_header_table(hd,noh);
	      if(!using_file) printf("ok!\n");
	    }
	  | LOAD PACKETS ':' EXPR {
	      packs2bsnt = load_packs($4,&nosp);
	      if(!packs2bsnt){
	        yyerror("There's not such file.");
		exit(1);
	      }
	      if(!using_file) printf("ok!\n");
	    }
	  | CREATE STATE STR {
              if(initiated){
                if(next_available != number_of_states){
		  if(debbug > 0)
                    printf("Creating state %s\n",$3);
                  current_state = insert_hash($3,hash_table,hash_size,next_available);
                  if(current_state>=0){
                    link_h2sv(hash_table,cell,current_state);
                    ++next_available;
                    if(!using_file) printf("ok!\n");
                  }else{
                     yyerror("Failed! State name already exists.");
                   }
                }else{
                   yyerror("Failed! The State Machine is FULL.");
                 }
              }else{
                 yyerror("Failed! Hashing table not initiated.");
               }
            }
	  | STATE STR action {
              if(initiated){
                current_state = check_state((char*)$2,hash_table,hash_size);
                if(current_state < 0){
                  yyerror("Failed! Non existent state.");
                }
		switch($3.action){
		  case SEND_PACKET:
		      action_send(cell,hash_table[current_state]->pos,\
		                  $3.snd.packet_id,$3.snd.next_state,nobt,but_chainl);
		      nobt = 0;
		      but_chainl = NULL;
		      bpivot = NULL;
		      baux = NULL;
		      if(!using_file) printf("ok!\n");
		    break;
		  case RECV_PACKET:
		      action_recv(cell,hash_table[current_state]->pos,\
		                  bpf_expr,iface,branches_chainl,nob,$3.rcv.to);
		      branches_chainl = NULL;
		      braux = NULL;
		      nob = 0;
		      if(!using_file) printf("ok!\n");
		    break;
		  case WAIT:
		      action_wait(cell,hash_table[current_state]->pos,\
		                  $3.wt.usec,$3.wt.next_state);
                      if(!using_file) printf("ok!\n");
		    break;
		  case SHELL:
		      action_shell(cell,hash_table[current_state]->pos, $3.sh);
		      if(!using_file) printf("ok!\n");
		    break;
		  case FINISH:
		      action_finish(cell,hash_table[current_state]->pos);
		      if(!using_file) printf("ok!\n");
		    break;
		};
              }else{
                 yyerror("Failed! Hashing table not initiated.");
               }
            }
          | SHOW state_table
	  | RESOLVE STR '.' STR {
	      finfo = gimme_the_data($2,$4,head_hash,noh,&aux);
	      if(finfo != NULL){
                printf("%d ",aux);
                printf("%s %d %d %d\nok!\n",finfo->fname,finfo->offset,finfo->size,finfo->swap);
              }else
	         yyerror("Failed! There's not such field/header.");
	    }
          | play 
          | VERBOSE on_off
	  | TERMINATE {
              if(!using_file) printf("bye-bye...%s:)%s\n",L_CYAN,L_GRAY);
	      fflush(stdout);
              get_out();
            }
	  ;

play: PLAY { lets_play(0); }
    | PLAY STR {
        if(initiated){
          current_state = check_state((char*)$2,hash_table,hash_size);
            if(current_state >= 0){
              lets_play(current_state);
            }else{
               yyerror("Failed! Non existent state.");
             }
        }else{
           yyerror("Failed! Hashing table not initiated.");
         }

      }
    ;

on_off: ON { verbose = 1; output_file = stdout; }
      | ON ':' EXPR {
          verbose = 1;
          output_file = fopen($3,"r");
              if(output_file == NULL){
                output_file = fopen($3,"w");
              }else{
                 fclose(output_file);
                 printf("\nLOG file: %s : already exists! Overwrite? (y/n)",$3);
                 fflush(stdout);
                 y_n_answ = getc(stdin);
                 if(y_n_answ == 'y'){
                   output_file = fopen($3,"w");
                 }else{
                    printf(" Using standard output...\n");
                    output_file = stdout;
                  }
               }
        }
      | OFF { verbose = 0; }
      ;

action: SEND_PACKET_T OPEN_BRACE PACK_ID ':' NUMBER but NEXT STATE ':' STR CLOSE_BRACE {
	  $$.action = SEND_PACKET;
	  $$.snd.packet_id = $5;
	  $$.snd.next_state = check_state((char*)$10,hash_table,hash_size);
	  if($$.snd.next_state < 0){
	    yyerror("Failed! There is not such state.");
	  }else{
	     $$.snd.next_state = hash_table[$$.snd.next_state]->pos;
	   }
	}
      | WAIT_T OPEN_BRACE time NEXT STATE ':' STR CLOSE_BRACE {
          $$.action = WAIT;
          $$.wt.usec = $3;
	  $$.wt.next_state = check_state((char*)$7,hash_table,hash_size);
	  if($$.snd.next_state < 0){
	    yyerror("Failed! There is not such state.");
	  }else{
	     $$.wt.next_state = hash_table[$$.wt.next_state]->pos;
	   }
        }
      | RECV_PACKET_T OPEN_BRACE BPF ':' EXPR IFACE ':' STR timeout branch_expr CLOSE_BRACE {
          $$.action = RECV_PACKET;
	  $$.rcv.to.time = $9.time;
	  $$.rcv.to.nxt = $9.nxt;
	  memset(bpf_expr,0,256);
	  memcpy(bpf_expr,$5,(strlen($5)+1)%256);
	  memset(iface,0,128);
	  memcpy(iface,$8,(strlen($8)+1)%128);
	  if(debbug > 0)
            printf("NoB %d\n",nob);
        }
      | SHELL_T OPEN_BRACE COMMAND ':' EXPR NEXT STATE ':' STR CLOSE_BRACE {
          $$.action = SHELL;
	  $$.sh.command = (char*)strdup($5);
	  $$.sh.next_state = check_state((char*)$9,hash_table,hash_size);
	  if($$.sh.next_state < 0){
	    yyerror("Failed! There is not such state.");
	  }else{
	     $$.sh.next_state = hash_table[$$.wt.next_state]->pos;
	   }
        }
      | FINISH_T {
          $$.action = FINISH;
        }
      ;

timeout: { $$.time = 0;
	   $$.nxt  = 0;
         }
       | TIMEOUT '=' time ':' STR {
           $$.time = $3;
	   $$.nxt = check_state((char*)$5,hash_table,hash_size);
	   if($$.nxt >= 0){
	     $$.nxt = hash_table[$$.nxt]->pos;
	   }
         }
       ;

branch_expr: b_expr
	   | b_expr PM_OR branch_expr
	   ;

b_expr: OPEN_BRACK NEXT STATE ':' STR CHECK ':' field_expr CLOSE_BRACK {
          braux = (struct brch_in*)malloc(sizeof(struct brch_in));
	  braux->info.nof = nof;
	  braux->info.next_state = check_state((char*)$5,hash_table,hash_size);
	  if(braux->info.next_state >= 0){
	    braux->info.next_state = hash_table[braux->info.next_state]->pos;
	  }
          braux->info.fld_vct = (struct field_off_bits*)malloc(nof*sizeof(struct field_off_bits));
          rlaux = rules_chainl;
	  aux = 0;
          while(rlaux != NULL){
	    rules_chainl = rlaux;
	    if(rules_chainl->info.layer>1){ /* If so, it has previous headers  */
	      braux->info.fld_vct[aux].pheaders = (struct phinf**)malloc(sizeof\
	                                          (struct phinf*)*rules_chainl->info.layer-1);
	    }else
	      braux->info.fld_vct[aux].pheaders = NULL;
	    for(i=0;i<rules_chainl->info.layer-1;i++){
	      braux->info.fld_vct[aux].pheaders[i] = rules_chainl->info.pheaders[i];
	    }
  	    braux->info.fld_vct[aux].layer = rules_chainl->info.layer;
	    braux->info.fld_vct[aux].offset = rules_chainl->info.offset;
	    braux->info.fld_vct[aux].size = rules_chainl->info.size;
	    braux->info.fld_vct[aux].info = rules_chainl->info.info;
	    aux++;
  	    rlaux = rlaux->next;
	    free(rules_chainl);
	  }
          if(branches_chainl == NULL){
            branches_chainl = braux;
            brpivot = braux;
	  }else{
	     brpivot->next = braux;
	     brpivot = brpivot->next;
	   }
          brpivot->next = NULL;
	  braux = NULL;
          rules_chainl = NULL;
	  if(debbug > 0)
            printf("NoF: %d\n",nof);
	  nof = 0;
	  ++nob;
        }
      ;

field_expr: f_expr
	  | f_expr PM_AND field_expr
	  ;

f_expr: ph_expr STR '.' STR EQUAL f_value_expr {
  	  finfo = gimme_the_data($2,$4,head_hash,noh,&aux);
	  if(noph+1 != aux){
	    yyerror("Hey! Tell me the previous headers! I can't guess it by myself!");
	  }else{
  	     if(finfo != NULL){
 	       ++nof;
	       rlaux = (struct rlz*)malloc(sizeof(struct rlz));
/*****************  Previous Header Information Delivery ********************/
	       rlaux->info.pheaders = NULL;
               if(pheaderl != NULL){
	         rlaux->info.pheaders = (struct phinf**)malloc(noph*sizeof(struct phinf*));
		 noph = 0;
	         phlaux = pheaderl->next;
	         while(pheaderl != NULL){
	           rlaux->info.pheaders[noph] = pheaderl->prvhinf;
	           ++noph;
	           free(pheaderl);
	           pheaderl = phlaux;
	           if(phlaux != NULL) phlaux = phlaux->next;
	         }
	       }
	       noph = 0;
/****************************************************************/
	       rlaux->info.layer	= aux;
	       rlaux->info.swap		= finfo->swap;
	       rlaux->info.offset	= finfo->offset;
	       rlaux->info.size		= finfo->size;
	       rlaux->next = NULL;
	       if(finfo->swap){
	         if(finfo->size >16)
	           rlaux->info.info	= htonl($6);
		 else
		   rlaux->info.info     = htons($6);
	       }else
	         rlaux->info.info       = $6;
	       if(rules_chainl == NULL){
	         rules_chainl = rlaux;
		 rlpivot = rlaux;
	       }else{
	          rlpivot->next = rlaux;
		  rlpivot = rlpivot->next;
	        }
	       rlaux = NULL;
             }else
	       yyerror("Failed! There's no such field!.");
	   }
   	}
      ;

f_value_expr: f_value {
                $$ = $1;
              }
	    | f_value OPER f_value {
	        switch($2){
		  case '+':
		    $$ = $1 + $3;
		  break;
		  case '-':
		    $$ = $1 - $3;
		  break;
		  case '*':
		    $$ = $1 * $3;
		  break;
		  case '/':
		    if($3 != 0)
		      $$ = $1 / $3;
		    else{
		      yyerror("Division by zero. Assuming result zero...");
		      $$ = 0;
		    }
		  break;
		  case '&':
		    $$ = $1 & $3;
		  break;
		  case '|':
		    $$ = $1 | $3;
		  break;
		  case '^':
		    $$ = $1 ^ $3;
		  break;
		}
	      }
	    ;

f_value: NUMBER {
           $$ = $1;
         }
       | CHAR {
           $$ = (u_int32_t)$1;
         }
       | '[' NUMBER ']' STR '.' STR { /* The local stored packets already have information
       				       *   about previous headers, so, all we need here are
				       *   the header and field names.
				       */
	   if($2 < 1 || $2 > nosp ){
	     yyerror("There is not such packid.");
	   }
           $$ = get_from_local_pack($2,$4,$6);
         }
       ;

ph_expr:
       | ph_expr_aux
       ;
       
ph_expr_aux: '>' 
           | OPEN_BRACE STR CLOSE_BRACE ph_expr_aux {
	       ++noph;
  	       phlaux = (struct phl*)malloc(sizeof(struct phl));
	       phlaux->prvhinf = (struct phinf*)malloc(sizeof(struct phinf));
	       finfo = gimme_the_data($2,"hlen",head_hash,noh,&aux);
	       phlaux->prvhinf->off = finfo->offset;
	       phlaux->prvhinf->size = finfo->size;
	       phlaux->next = pheaderl;
	       pheaderl = phlaux;
             }
           ;

but: 
   | BUT ':' but_expr
   ;

but_expr: bu_expr
	| bu_expr PM_AND but_expr
	;

bu_expr: b_field '=' but_oper {
           ++nobt;
           baux = (struct but_in*)malloc(sizeof(struct but_in));
	   baux->but = (struct but*)malloc(sizeof(struct but));
           memcpy(baux->but,&$3,sizeof(struct but));
	   baux->but->field = (struct field_off_bits*)malloc(sizeof(struct field_off_bits));
	   memcpy(baux->but->field,&$1,sizeof(struct field_off_bits));
	   memset(&$3,0,sizeof(struct but));
	   if(but_chainl == NULL){
	     but_chainl = baux;
	     but_chainl->next = NULL;
	     bpivot = but_chainl;
	   }else{
	       bpivot->next = baux;
	       bpivot = bpivot->next;
	       bpivot->next = NULL;
	    }
        }
      ;

b_field: ph_expr STR '.' STR {
           finfo = gimme_the_data($2,$4,head_hash,noh,&aux);
	   if(finfo == NULL){
	     yyerror("I don't know this field!");
	   }
	   if(noph+1 != aux){
	     yyerror("Hey! Tell me the previous headers! I can't guess it by myself!");
	   }else{
	     if(finfo != NULL){
	       /***************  Previous Header Information Delivery **********/
	       $$.pheaders = NULL;
	       if(pheaderl != NULL){
	         $$.pheaders = (struct phinf**)malloc(noph*sizeof(struct phinf*));
	         noph = 0;
	         phlaux = pheaderl->next;
	         while(pheaderl != NULL){
	           $$.pheaders[noph] = pheaderl->prvhinf;
	           ++noph;
		   free(pheaderl);
		   pheaderl = phlaux;
		   if(phlaux != NULL) phlaux = phlaux->next;
	         }
	       }
	       noph = 0;
	       /****************************************************************/
	       $$.layer		= aux;
	       $$.swap		= finfo->swap;
	       $$.offset	= finfo->offset;
	       $$.size 		= finfo->size;
	       $$.info 		= 0;
	     }else
	       yyerror("Failed! There's no such field!.");
	   }
         }
       ;

but_oper: but_data {
            $$.args = (struct but_args**)malloc(sizeof(struct but_args*));
	    $$.args[0] = (struct but_args*)malloc(sizeof(struct but_args*));
	    $$.operation = NOP;
	    memcpy($$.args[0],&$1,sizeof(struct but_args));
          }
        | but_data OPER but_data {
	    $$.args = (struct but_args**)malloc(2*sizeof(struct but_args*));
	    $$.args[0] = (struct but_args*)malloc(sizeof(struct but_args*));
	    $$.args[1] = (struct but_args*)malloc(sizeof(struct but_args*));
	    switch($2){
	      case '+':
	        $$.operation = ADD;
	      break;
	      case '-':
	        $$.operation = SUB;
	      break;
	      case '*':
	        $$.operation = MUL;
	      break;
	      case '/':
	        $$.operation = DIV;
	      break;
	      case '&':
	        $$.operation = AND;
	      break;
	      case '|':
	        $$.operation = OR;
	      break;
	      case '^':
	        $$.operation = XOR;
	      break;
	    }
	    memcpy($$.args[0],&$1,sizeof(struct but_args));
	    memcpy($$.args[1],&$3,sizeof(struct but_args));
	  }
	;

but_data: NUMBER {			/* Immediate 		*/
            $$.type = IMMEDIATE;
	    $$.bi_arg = (struct immediate_arg*)malloc(sizeof(struct immediate_arg));
	    $$.bi_arg->value = $1;
          }
        | f_addr {                      /* This Packet          */
	    $$.type = THIS_PACKET;
	    $$.bp_arg = (struct pack_arg*)malloc(sizeof(struct pack_arg));
	    $$.bp_arg->pnum = 0;
	    memcpy(&($$.bp_arg->field),&$1,sizeof(struct field_off_bits));
	    memset(&$1,0,sizeof(struct field_off_bits));
	  }
	| '[' NUMBER ']' f_addr {       /* Stored Packet        */
	    if($2 == 0 || $2 > nosp){
	      yyerror("There is no such packid.");
	    }
	    $$.type = STORED_PACKET;
	    $$.bp_arg = (struct pack_arg*)malloc(sizeof(struct pack_arg));
	    $$.bp_arg->pnum = $2;
	    memcpy(&($$.bp_arg->field),&$4,sizeof(struct field_off_bits));
	    memset(&$4,0,sizeof(struct field_off_bits));
	  }
	| '[' STR ']' f_addr {		/* Received Packet	*/ 
	    $$.type = RECEIVED_PACKET;
	    $$.bp_arg = (struct pack_arg*)malloc(sizeof(struct pack_arg));
	    i = check_state((char*)$2,hash_table,hash_size);
	    if(i >= 0){
	      $$.bp_arg->pnum = hash_table[i]->pos;
	    }else{
	       yyerror("Failed! There's no such state!.");
	     }
	    memcpy(&($$.bp_arg->field),&$4,sizeof(struct field_off_bits));
	    memset(&$4,0,sizeof(struct field_off_bits));
	  }
	| STD_CHECKSUM OPEN_BRACK STR CLOSE_BRACK {
	    $$.type = STD_CKSUM;
	    $$.bc_arg = (struct cksum_arg*)malloc(sizeof(struct cksum_arg));
	    $$.bc_arg->header = (u_char*)strdup($3);
	  }
	;

f_addr: ph_expr STR '.' STR {
          finfo = gimme_the_data($2,$4,head_hash,noh,&aux);
	  if(finfo == NULL){
	    yyerror(" I don't know this field!");
	  }
	  if(noph+1 != aux){
	    yyerror("Hey! Tell me the previous headers! I can't guess it by myself!");
	  }else{
	    if(finfo != NULL){
	      /*****************  Previous Header Information Delivery ********************/
	      $$.pheaders = NULL;
	      if(pheaderl != NULL){
	        $$.pheaders = (struct phinf**)malloc(noph*sizeof(struct phinf*));
		noph = 0;
		phlaux = pheaderl->next;
		while(pheaderl != NULL){
		  $$.pheaders[noph] = pheaderl->prvhinf;
		  ++noph;
		  free(pheaderl);
		  pheaderl = phlaux;
		  if(phlaux != NULL) phlaux = phlaux->next;
		}
	      }
	      noph = 0;
	      /****************************************************************/
	      $$.layer	= aux;
	      $$.swap	= finfo->swap;
	      $$.offset	= finfo->offset;
	      $$.size	= finfo->size;
	      $$.info	= 0;
	    }else
	      yyerror("Failed! There's no such field!.");
	     }
        }
      ;

time: U_SEC {  /* time in microseconds */
	  $$ = $1;
      }
    | M_SEC { /* time in miliseconds */
	  $$ = 1000*$1;
        }
    ;

state_table: ALL {
               show_all(cell,number_of_states);
               printf("ok!\n");
             }
           | USED {
               show_all(cell,next_available);
               printf("ok!\n");
             }
           | STATE show_type
           ;

show_type: NUMBER {
             show_state(cell,$1);
             printf("ok!\n");
           }
         | STR {
             if(initiated){
               current_state = check_state((char*)$1,hash_table,hash_size);
               if(current_state >= 0){
                 show_state(cell,hash_table[current_state]->pos);
                 printf("ok!\n");
               }else{
                  yyerror("Failed! Non existent state.");
                }
             }else{
                yyerror("Failed! Hashing table not initiated.");
              }
           }
         ;
%%

extern  FILE		*yyin;

main(int argc, char**argv){
  FILE *file;

  printf("Pack%sMan%s 20/03/2002 v0.9 - Daniel Pupim Kano\n",D_CYAN,L_GRAY);
  printf("Supervised by PhD. Prof. Paulo Licio de Geus -- Sponsored by %sFAPESP%s\n\n",L_BLUE,L_GRAY);

  if(argc > 1){
    if(!memcmp(argv[1]+(strlen(argv[1])-4),".las",4)){
      using_file = 1;
      file = fopen(argv[1],"r");
      yyin = file;
    }else{
       printf("It is not a Pack%sMan%s file.\n",D_CYAN,L_GRAY);
     }
   }else
      yyin = stdin;

   while(1){
     yyparse();
   }

  return 0;
}

yyerror(s)
char *s;
{
    fprintf(stderr, "%d: %s at %s\n",lineno , s, yytext);
    exit(0);
}

