config.fl 33.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*****************************************************************************
 * config.fl
 * Generate a parser for the config file 
 *****************************************************************************
 * Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
 * $Id: config.fl,v 1.18 2001/04/29 03:41:49 nitrox Exp $
 *
 * Authors: Brieuc Jeunhomme <bbp@via.ecp.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

25
%pointer
26
%option nounput
27 28 29 30

%{

  
31 32
#include <arpa/inet.h>                                            /* types.h */
#include <string.h>                                       /* strdup, strncmp */
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

#include "../types.h"
#include "../logger.h"
#include "../config.h"
#include "config.h"

struct CFG_SWITCH_TYPE *CFG_switch_type(struct VS_config *cfg,\
                                        char *switch_type_name)
{
  struct CFG_SWITCH_TYPE *z;

  for (z=cfg->switch_types;z!=NULL;z=z->next)
    if (!strcmp(CFG_SWITCH_TYPE_NAME(*z),switch_type_name))
      break;
  return z;
}


#define YY_DECL static ERR_CODE CFG_yylex(struct VS_config *cfg,char *filename)

inline int CFG_yywrap(void) {return 1;}


%}


59 60 61
BL		    [ \t]+
FB		    [ \t]*
INT		    [0-9]+
62
NONBLANK	[^ \t\n]
63
IP        ([0-9]{1,3}[.]){3}([0-9]{1,3})
64
DNS       ([A-Za-z0-9-]+[.])*[A-Za-z0-9-]+[.]*
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88

%x in_channel_raw_data
%x in_switch_type
%x in_switch


%%


%{

        unsigned long ul1;
        unsigned long ul2;
        unsigned int ui1;
        unsigned int i;
        unsigned int line_num;
        unsigned int eof_expected;
        unsigned int raw_data_allowed;
        struct CFG_SWITCH_TYPE **st;
        struct CFG_SWITCH **s;
        struct CFG_SWITCH_TYPE *z;
        VS_SwitchId ip;
        struct CFG_PORT *ports;
        char c;
89
        
Damien Lucas's avatar
Damien Lucas committed
90 91
        raw_data_allowed=0;
        z=NULL;
92 93 94 95
        line_num=1;
        eof_expected=1;
        for(st=&(cfg->switch_types);*st!=NULL;st=&((*st)->next));
        for(s=&(cfg->zwitches);*s!=NULL;s=&((*s)->next));
96
        ports=NULL;
97 98 99 100 101 102 103 104 105
        
%}


<*>^{BL}        ;

<*>{FB}\n       line_num++;


106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

logfile{BL}{NONBLANK}+   {
        if (cfg->logfile!=NULL)
        {
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : duplicated "\
                       "logfile",filename,line_num);
          return VS_R_PARSE;
        }
        for (ui1=CFG_yyleng-1;\
             CFG_yytext[ui1-1]!=' ' && CFG_yytext[ui1-1]!='\t';ui1--);
        cfg->logfile=malloc((CFG_yyleng-ui1+1)*sizeof(char));
        if (cfg->logfile==NULL)
        {
          VS_log(LOGERROR,CFG,"Unable to allocate memory to store logfile");
          return VS_R_MEMORY;
        }
        memcpy(cfg->logfile,CFG_yytext+ui1,CFG_yyleng-ui1);
        cfg->logfile[CFG_yyleng-ui1]=0;
                        }



logmethod{BL}{INT}      {
        if (cfg->logmethod)
        {
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : logemthod has "\
                       "already been defined",filename,line_num);
          return VS_R_PARSE;
        }
        sscanf(CFG_yytext+sizeof("logmethod")/sizeof(char)-1," %lu",&ul1);
        if (ul1>LOG_BOTH)
        {
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : logmethod out "\
                       "of range",filename,line_num);
          return VS_R_PARSE;
        }
        cfg->logmethod=ul1;
                        }
  
145 146 147 148
nchannels{BL}{INT}      {

        if (cfg->nchannels)
        {
149
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : nchannels has "\
150
                       "already been defined",filename,line_num);
151 152 153 154 155
          return VS_R_PARSE;
        }
        sscanf(CFG_yytext+sizeof("nchannels")/sizeof(char)-1," %lu",&ul1);
        if (!ul1)
        {
156
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : nchannels can't "\
157
                       "be 0",filename,line_num);
158 159 160
          return VS_R_PARSE;
        }
        cfg->nchannels=(VS_CHANNEL)ul1;
161
        VS_log(LOGDEBUG,CFG,"Number of channels set to : %lu",ul1);
162 163 164
        cfg->chan_map=malloc(ul1*sizeof(struct CFG_CHANNEL));
        if (cfg->chan_map==NULL)
        {
165 166
          VS_log(LOGERROR,CFG,"Unable to allocate memory to create the"\
              "channels table");
167 168 169 170 171 172 173 174 175 176 177 178 179 180
          return VS_R_MEMORY;
        }
      do
        {
          ul1--;
          cfg->chan_map[ul1].raw_data=NULL;
          cfg->chan_map[ul1].protection=(VS_PROTECTION_LEVEL)VS_PL_UNSPECIFIED;
          // TODO I guess the following line is useless, it should probably be
          // removed
          cfg->chan_map[ul1].vlan=0;
        } while(ul1);

                        }

181
vlanbridge{BL}{DNS}         {
182

183
        if (cfg->vlanbridge!=NULL)
184
        {
185
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : duplicated "\
186
                       "vlanbridge address defition",filename,line_num);
187 188 189 190
          return VS_R_PARSE;
        }
        for (ui1=CFG_yyleng-1;\
             CFG_yytext[ui1-1]!=' ' && CFG_yytext[ui1-1]!='\t';ui1--);
191
        cfg->vlanbridge=strdup(CFG_yytext+ui1);
192

193
                                }
194 195 196 197 198

vlanbridge_login{BL}{NONBLANK}+ {

        if (cfg->vlanbridge_login!=NULL)
        {
199
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : duplicated "\
200
                       "vlanbridge login",filename,line_num);
201 202 203 204 205 206 207
          return VS_R_PARSE;
        }
        for (ui1=CFG_yyleng-1;\
             CFG_yytext[ui1-1]!=' ' && CFG_yytext[ui1-1]!='\t';ui1--);
        cfg->vlanbridge_login=malloc((CFG_yyleng-ui1+1)*sizeof(char));
        if (cfg->vlanbridge_login==NULL)
        {
208
          VS_log(LOGERROR,CFG,"Unable to allocate memory to store vlanbridge "\
209
                       "login");
210 211 212 213 214 215 216 217 218 219 220
          return VS_R_MEMORY;
        }
        memcpy(cfg->vlanbridge_login,CFG_yytext+ui1,CFG_yyleng-ui1);
        cfg->vlanbridge_login[CFG_yyleng-ui1]=0;

                                }

vlanbridge_password{BL}{NONBLANK}+ {

        if (cfg->vlanbridge_password!=NULL)
        {
221
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : duplicated "\
222
                       "vlanbridge password",filename,line_num);
223 224 225 226 227 228 229
          return VS_R_PARSE;
        }
        for (ui1=CFG_yyleng-1;\
             CFG_yytext[ui1-1]!=' ' && CFG_yytext[ui1-1]!='\t';ui1--);
        cfg->vlanbridge_password=malloc((CFG_yyleng-ui1+1)*sizeof(char));
        if (cfg->vlanbridge_password==NULL)
        {
230
          VS_log(LOGERROR,CFG,"Unable to allocate memory to store VLB "\
231
                       "password");
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
          return VS_R_MEMORY;
        }
        memcpy(cfg->vlanbridge_password,CFG_yytext+ui1,CFG_yyleng-ui1);
        cfg->vlanbridge_password[CFG_yyleng-ui1]=0;

                                   }

channel{BL}{INT}{BL}vlan{BL}{INT}{BL}protection{BL}{INT}{BL}    {

        sscanf(CFG_yytext+sizeof("channel")/sizeof(char)-1,\
               " %lu vlan %lu protection %u",&ul1,&ul2,&ui1);
        BEGIN(in_channel_raw_data);
        eof_expected=0;
        raw_data_allowed=1;

                                                                }


channel{BL}{INT}{BL}vlan{BL}{INT}{BL}protection{BL}{INT}	{

        sscanf(CFG_yytext+sizeof("channel")/sizeof(char)-1,\
               " %lu vlan %lu protection %u",&ul1,&ul2,&ui1);
        BEGIN(in_channel_raw_data);
        eof_expected=0;
        raw_data_allowed=0;

                                                                }


<in_channel_raw_data>.*\n       {

        if ((VS_CHANNEL)ul1>=cfg->nchannels)
        {
265
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : invalid channel "\
266
                       "number",filename,line_num);
267 268 269 270
          return VS_R_PARSE;
        }
        if (cfg->chan_map[ul1].protection!=VS_PL_UNSPECIFIED)
        {
271
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : channel %lu has"\
272
                       " already been defined",filename,line_num,ul1);
273 274 275 276
          return VS_R_PARSE;
        }
        if ((VS_PROTECTION_LEVEL)ui1>=VS_PL_NUMBER)
        {
277 278
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u: protection levels"\
                       " range from 0 to %lu",filename,line_num,\
279 280 281 282 283
                       (unsigned long)VS_PL_NUMBER-1);
          return VS_R_PARSE;
        }
        if (!raw_data_allowed && CFG_yyleng)
        {
284
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : expecting "\
285
                       "integer",filename,line_num);
286 287 288 289 290
          return VS_R_PARSE;
        }
        cfg->chan_map[ul1].raw_data=malloc((CFG_yyleng+1)*sizeof(char));
        if (cfg->chan_map[ul1].raw_data==NULL)
        {
291 292
          VS_log(LOGERROR,CFG,"Unable to allocate memory to store raw data"\
                       " for channel %lu",ul1);
293 294 295 296 297 298 299 300 301 302
          return VS_R_MEMORY;
        }
        memcpy(cfg->chan_map[ul1].raw_data,CFG_yytext,\
               (CFG_yyleng-1)*sizeof(char));
        cfg->chan_map[ul1].raw_data[CFG_yyleng]=0;
        cfg->chan_map[ul1].vlan=(VS_VLAN)ul2;
        cfg->chan_map[ul1].protection=(VS_PROTECTION_LEVEL)ui1;
        line_num++;
        BEGIN(INITIAL);
        eof_expected=1;
303
        CFG_yytext[strlen(CFG_yytext)-1]='\0';
304
        VS_log(LOGDEBUG,CFG,"Successfuly defined channel %lu on vlan "\
305 306 307 308 309 310 311 312 313 314 315 316
                    "%lu protection %u %s",ul1,ul2,ui1,CFG_yytext);

                                }


switch{BL}type{BL}{NONBLANK}+   {

        for (i=CFG_yyleng-1;CFG_yytext[i-1]!=' ' && CFG_yytext[i-1]!='\t';i--);
        *st=malloc(sizeof(struct CFG_SWITCH_TYPE)+\
                   (CFG_yyleng-i+1)*sizeof(char));
        if (*st==NULL)
        {
317
          VS_log(LOGERROR,CFG,"Unable to allocate memory to create a switch "\
318
                       "type");
319 320 321
          return VS_R_MEMORY;
        }
        (*st)->nports=(VS_PORT)0;
322
        (*st)->unit=VS_UNIT_UNSPECIFIED;
323
        (*st)->ports=((struct CFG_PORT *)NULL)-1;
324 325 326 327 328 329 330 331 332 333 334 335 336 337
        (*st)->next=NULL;
        memcpy(CFG_SWITCH_TYPE_NAME(**st),CFG_yytext+i,\
               (CFG_yyleng-i)*sizeof(char));
        CFG_SWITCH_TYPE_NAME(**st)[CFG_yyleng-i]=0;
        BEGIN(in_switch_type);
        eof_expected=0;

                                }


<in_switch_type>nports{BL}{INT} {

        if ((*st)->nports)
        {
338
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : nports has "\
339
                       "already been defined",filename,line_num);
340 341 342 343 344 345 346 347 348
          return VS_R_PARSE;
        }
        sscanf(CFG_yytext+sizeof("nports")/sizeof(char)-1," %lu",&ul1);
        (*st)->nports=(VS_PORT)ul1;
        (*st)->ports=malloc(ul1*sizeof(struct CFG_PORT));
        /* UGLY, but we don't wanna waste memory nor cpu, do we ? */
        (*st)->ports--;
        if ((((*st)->ports)+1)==NULL)
        {
349
          VS_log(LOGERROR,CFG,"Unable to allocate memory to store a switch "\
350
                       "type's ports table");
351 352 353 354 355
          return VS_R_MEMORY;
        }
        do
        {
          (*st)->ports[ul1].protection=VS_PL_UNSPECIFIED;
356
          (*st)->ports[ul1].flags=0;
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
          ul1--;
        } while (ul1);

                                }

<in_switch_type>model{BL}{NONBLANK}+    {

        {
          unsigned int i;
          i=6;
          while (CFG_yytext[i]==' ' || CFG_yytext[i]=='\t')
          {
            i++;
          }
          if (!strncmp(CFG_yytext+i,"3C1000",CFG_yyleng-i))
          {
            (*st)->type=VS_ST_3C1000;
          }
375 376 377 378
          else if (!strncmp(CFG_yytext+i,"3CDESK",CFG_yyleng-i))
          {
            (*st)->type=VS_ST_3CDESK;
          }
379 380 381 382 383 384 385 386 387 388
          else if (!strncmp(CFG_yytext+i,"3C1100",CFG_yyleng-i))
          {
            (*st)->type=VS_ST_3C1100;
          }
          else if (!strncmp(CFG_yytext+i,"3C3300",CFG_yyleng-i))
          {
            (*st)->type=VS_ST_3C3300;
          }
          else
          {
389
            VS_log(LOGERROR,CFG,"Parse error in %s on line %u: unknown switch "\
390
                         "type",filename,line_num);
391 392 393 394 395 396 397 398 399 400 401
            return VS_R_PARSE;
          }
        }

                                        }

<in_switch_type>default{BL}{INT}        {

        sscanf(CFG_yytext+sizeof("default")/sizeof(char)-1," %u",&ui1);
        if (ui1>=VS_PL_NUMBER)
        {
402 403
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u: protection levels"\
                       " range from 0 to %lu",filename,line_num,\
404 405 406 407 408 409 410 411 412 413 414
                       (unsigned long)VS_PL_NUMBER-1);
          return VS_R_PARSE;
        }
        i=0;
        for (ul1=(unsigned long)(*st)->nports;ul1;ul1--)
          if ((*st)->ports[ul1].protection==VS_PL_UNSPECIFIED)
          {
            (*st)->ports[ul1].protection=(VS_PROTECTION_LEVEL)ui1;
            i=1;
          }
        if (!i)
415 416
          VS_log(LOGWARNING,CFG,"In %s on line %u : useless 'default' "\
                       "statement in switch type definition, going on "\
417
                       "however",filename,line_num);
418 419 420 421

                                        }


422 423 424 425 426
<in_switch_type>unit{BL}{INT}           {
        sscanf(CFG_yytext+sizeof("unit")/sizeof(char)-1," %u",&ui1);
        if (ui1>VS_UNIT_MAX || ui1<1)
        {
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : Switch unit "\
427
                                      "range from 1 to %lu",filename,line_num,\
428 429 430 431 432
                                                   (unsigned long)VS_UNIT_MAX);
          return VS_R_PARSE;
        }
        (*st)->unit=(VS_UNIT)ui1;
        VS_log(LOGINFO,CFG,"Switch type %s on unit %u",\
433
                                               CFG_SWITCH_TYPE_NAME(**st),ui1);
434 435 436
                                        }


437 438
<in_switch_type>port{BL}{INT}{BL}{INT}  {

439 440
        if (!(*st)->nports)
        {
441
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u: number of ports"\
442
                 "unknown yet", filename, line_num);
443 444
          return VS_R_PARSE;
        }
445
        sscanf(CFG_yytext+sizeof("port")/sizeof(char)-1, " %lu %u", &ul1,\
446
               &ui1);
447 448
        if (!ul1 || (VS_PORT)ul1>(*st)->nports)
        {
449
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u : invalid port "\
450
                       "number", filename, line_num);
451 452 453 454
          return VS_R_PARSE;
        }
        if ((VS_PROTECTION_LEVEL)ui1>=VS_PL_NUMBER)
        {
455 456
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u : protection "\
                 "levels range from 0 to %u", filename, line_num,\
457
                       (unsigned int)VS_PL_NUMBER-1);
458
          return VS_R_PARSE;
459 460 461 462 463
        }
        (*st)->ports[ul1].protection=(VS_PROTECTION_LEVEL)ui1;

                                        }

464 465 466 467
<in_switch_type>bbports({BL}{INT})+     {

        if (!(*st)->nports)
        {
468
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u: number of ports"\
469
                 "unknown yet", filename, line_num);
470 471 472 473 474 475 476 477 478 479 480
        }
        {
          unsigned int i;
          unsigned int j;

          for (i=sizeof("bbports")/sizeof(char)-1;i<CFG_yyleng;i+=j)
          {
            ul1=0;
            sscanf(CFG_yytext+i, " %lu%n", &ul1, &j);
            if (!ul1 || ul1>(*st)->nports)
            {
481
              VS_log(LOGERROR, CFG, "Parse error in %s on line %u : invalid"\
482
                     "port number", filename, line_num);
483 484 485 486 487 488 489 490 491 492 493 494 495
              return VS_R_PARSE;
            }
            (*st)->ports[ul1].flags|=PF_BBPORT;
          }
        }

                                        }


<in_switch_type>atmports({BL}{INT})+     {

        if (!(*st)->nports)
        {
496
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u: number of ports"\
497
                 "unknown yet", filename, line_num);
498 499 500 501 502 503 504 505 506 507 508
        }
        {
          unsigned int i;
          unsigned int j;

          for (i=sizeof("atmports")/sizeof(char)-1;i<CFG_yyleng;i+=j)
          {
            ul1=0;
            sscanf(CFG_yytext+i, " %lu%n", &ul1, &j);
            if (!ul1 || ul1>(*st)->nports)
            {
509
              VS_log(LOGERROR, CFG, "Parse error in %s on line %u : invalid "\
510
                     "port number", filename, line_num);
511 512 513 514 515 516 517 518 519 520 521 522 523
              return VS_R_PARSE;
            }
            (*st)->ports[ul1].flags|=PF_ATMPORT;
          }
        }

                                        }


<in_switch_type>aobports({BL}{INT})+     {

        if (!(*st)->nports)
        {
524
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u: number of ports"\
525
                 "unknown yet", filename, line_num);
526 527 528 529 530 531 532 533 534 535 536
        }
        {
          unsigned int i;
          unsigned int j;

          for (i=sizeof("aobports")/sizeof(char)-1;i<CFG_yyleng;i+=j)
          {
            ul1=0;
            sscanf(CFG_yytext+i, " %lu%n", &ul1, &j);
            if (!ul1 || ul1>(*st)->nports)
            {
537
              VS_log(LOGERROR, CFG, "Parse error in %s on line %u : invalid "\
538
                     "port number", filename, line_num);
539 540 541 542 543 544 545 546 547 548 549 550 551
              return VS_R_PARSE;
            }
            (*st)->ports[ul1].flags|=PF_AOBPORT;
          }
        }

                                        }


<in_switch_type>hubports({BL}{INT})+    {

        if (!(*st)->nports)
        {
552
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u: number of ports"\
553
                 "unknown yet", filename, line_num);
554 555 556 557 558 559 560 561 562 563 564
        }
        {
          unsigned int i;
          unsigned int j;

          for (i=sizeof("hubports")/sizeof(char)-1;i<CFG_yyleng;i+=j)
          {
            ul1=0;
            sscanf(CFG_yytext+i, " %lu%n", &ul1, &j);
            if (!ul1 || ul1>(*st)->nports)
            {
565
              VS_log(LOGERROR, CFG, "Parse error in %s on line %u : invalid "\
566
                     "port number", filename, line_num);
567 568 569 570 571 572 573 574
              return VS_R_PARSE;
            }
            (*st)->ports[ul1].flags|=PF_HUBPORT;
          }
        }

                                        }

575 576 577 578 579 580

<in_switch_type>end{BL}switch{BL}type   {

        for (ul1=1;(VS_PORT)ul1<=(*st)->nports;ul1++)
          if ((*st)->ports[ul1].protection==VS_PL_UNSPECIFIED)
          {
581
            VS_log(LOGERROR,CFG,"Parse error in %s on line %u: switch type %s "\
582
                         "has not been completely specified",filename,\
583 584 585
                         line_num,CFG_SWITCH_TYPE_NAME(**st));
            return VS_R_PARSE;
          }
586 587
        VS_log(LOGDEBUG,CFG,"Switch type %s defined with the %lu following"\
                      "ports :",CFG_SWITCH_TYPE_NAME(**st),\
588 589
                    (unsigned long)(*st)->nports);
        for (ul1=1;(VS_PORT)ul1<=(*st)->nports;ul1++)
590
          VS_log(LOGDEBUG,CFG," Port %lu :\tprotection %lu \tflags %lu",ul1,\
591 592
                      (unsigned long)(*st)->ports[ul1].protection,\
                      (unsigned long)(*st)->ports[ul1].flags);
593 594 595 596 597 598 599
        st=&((*st)->next);
        BEGIN(INITIAL);
        eof_expected=1;

					}


600
{NONBLANK}+{BL}{IP}                     {
601 602 603 604 605 606 607

        for (i=0;CFG_yytext[i]!=' ' && CFG_yytext[i]!='\t';i++);
        c=CFG_yytext[i];
        CFG_yytext[i]=0;
        z=CFG_switch_type(cfg,CFG_yytext);
        if (z==NULL)
        {
608
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : unknown switch "\
609
                       "type",filename,line_num);
610 611 612 613 614 615
          return VS_R_PARSE;
        }
        CFG_yytext[i]=c;
        for(i=CFG_yyleng-1;CFG_yytext[i-1]!=' ' && CFG_yytext[i-1]!='\t';i--);
        if (!VS_A2SID(CFG_yytext+i,ip))
        {
616
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : invalid IP "\
617
                       "address",filename,line_num);
618 619 620 621 622 623 624
          return VS_R_PARSE;
        }
        
        // need to malloc s
        *s=malloc(sizeof(struct CFG_SWITCH));
        if(*s==NULL)
        {
625 626
                VS_log(LOGERROR,CFG,"Unable to allocate memory to create a "\
                             "new switch in the database");
627 628 629 630 631
                return VS_R_MEMORY;
        }
        
        // and complete s
        (*s)->ip=ip;
632
        (*s)->unit=z->unit;
633 634 635 636 637
        (*s)->nports=z->nports;
        (*s)->type=z->type;
        (*s)->next=NULL;
        (*s)->community=NULL;

638
        ports=malloc(z->nports*sizeof(struct CFG_PORT));
639 640 641
        /* UGLY, but we don't wanna waste memory nor cpu, do we ? */
        if (ports==NULL)
        {
642 643
          VS_log(LOGERROR,CFG,"Unable to allocate memory to create a "\
              "new switch in the database");
644 645 646 647
          return VS_R_MEMORY;
        }
        ports--;
        for (ul2=1;(VS_PORT)ul2<=z->nports;ul2++)
648
        {
649
          ports[ul2].protection=z->ports[ul2].protection;
650 651
          ports[ul2].flags=z->ports[ul2].flags;
        }
652
        VS_log(LOGINFO,CFG,"Creating switch %s with type %s (%lu ports)...",\
653 654 655 656
                    CFG_yytext+i,CFG_SWITCH_TYPE_NAME(*z),ul2-1);
        BEGIN(in_switch);
        eof_expected=0;

657
                                        }
658 659 660 661 662 663 664 665 666 667


<in_switch>community{BL}{NONBLANK}+     {

        for (i=CFG_yyleng-1;CFG_yytext[i-1]!=' ' && CFG_yytext[i]!='\t';i--);
        (*s)->community=malloc((CFG_yyleng-i+1)*sizeof(char));
        if ((*s)->community==NULL)
        {
          ports++;
          free(ports);
668
          VS_log(LOGERROR,CFG,"Unable to allocate memory to store a switch's "\
669
                       "community string");
670
          return VS_R_MEMORY;
671 672 673 674 675 676 677 678 679 680 681
        }
        memcpy((*s)->community,CFG_yytext+i,CFG_yyleng-i);
        (*s)->community[CFG_yyleng-i]=0;

                                        }

<in_switch>port{BL}{INT}{BL}{INT}       {

        sscanf(CFG_yytext+sizeof("port")/sizeof(char)-1," %lu %u",&ul1,&ui1);
        if ((VS_PORT)ul1>z->nports || !ul1)
        {
682
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : invalid port "\
683
                       "number",filename,line_num);
684 685 686 687 688 689
          ports++;
          free(ports);
          return VS_R_PARSE;
        }
        if ((VS_PROTECTION_LEVEL)ui1>=VS_PL_NUMBER)
        {
690
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u: protection levels"\
691
                       "range from 0 to %u",filename,line_num,\
692 693 694 695 696 697
                       (unsigned int)ui1);
          ports++;
          free(ports);
          return VS_R_PARSE;
        }
        ports[ul1].protection=(VS_PROTECTION_LEVEL)ui1;
698
        VS_log(LOGINFO,CFG," Protection of port %lu set to %u",ul1,ui1);
699 700 701

                                        }

702 703 704 705 706 707 708 709 710 711 712
<in_switch>unit{BL}{INT}                {
        sscanf(CFG_yytext+sizeof("unit")/sizeof(char)-1," %u",&ui1);
        if (ui1>VS_UNIT_MAX || ui1<1)
        {
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u : invalid unit "\
                                               "number",filename,line_num);
          return VS_R_PARSE;
                    
        }
        (*s)->unit=ui1;
        VS_log(LOGINFO,CFG,"  Unit of switch set to %u",ui1);
713

714
                                        }
715 716 717 718
<in_switch>bbports({BL}{INT})+          {

        if (!(*s)->nports)
        {
719
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u: number of ports"\
720
                 "unknown yet", filename, line_num);
721 722 723 724 725 726 727 728 729 730 731
        }
        {
          unsigned int i;
          unsigned int j;

          for (i=sizeof("bbports")/sizeof(char)-1;i<CFG_yyleng;i+=j)
          {
            ul1=0;
            sscanf(CFG_yytext+i, " %lu%n", &ul1, &j);
            if (!ul1 || ul1>(*s)->nports)
            {
732
              VS_log(LOGERROR, CFG, "Parse error in %s on line %u : invalid "\
733
                     "port number", filename, line_num);
734 735 736 737 738
              return VS_R_PARSE;
            }
            ports[ul1].flags|=PF_BBPORT;
          }
        }
739
        VS_log(LOGINFO,CFG," Flag of port %lu set to %u",ul1,\
740
               ports[ul1].flags);
741 742 743 744 745 746 747 748 749


                                        }


<in_switch>atmports({BL}{INT})+         {

        if (!(*s)->nports)
        {
750
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u: number of ports"\
751
                 "unknown yet", filename, line_num);
752 753 754 755 756 757 758 759 760 761 762
        }
        {
          unsigned int i;
          unsigned int j;

          for (i=sizeof("atmports")/sizeof(char)-1;i<CFG_yyleng;i+=j)
          {
            ul1=0;
            sscanf(CFG_yytext+i, " %lu%n", &ul1, &j);
            if (!ul1 || ul1>(*s)->nports)
            {
763
              VS_log(LOGERROR, CFG, "Parse error in %s on line %u : invalid "\
764
                     "port number", filename, line_num);
765 766 767 768 769
              return VS_R_PARSE;
            }
            ports[ul1].flags|=PF_ATMPORT;
          }
        }
770
        VS_log(LOGINFO,CFG," Flag of port %lu set to %u",ul1,\
771
               ports[ul1].flags);
772 773 774 775 776 777 778 779 780


                                        }


<in_switch>aobports({BL}{INT})+         {

        if (!(*s)->nports)
        {
781 782
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u : number of"\
                    "ports unknown yet", filename, line_num);
783 784 785 786 787 788 789 790 791 792 793
        }
        {
          unsigned int i;
          unsigned int j;

          for (i=sizeof("aobports")/sizeof(char)-1;i<CFG_yyleng;i+=j)
          {
            ul1=0;
            sscanf(CFG_yytext+i, " %lu%n", &ul1, &j);
            if (!ul1 || ul1>(*s)->nports)
            {
794
              VS_log(LOGERROR, CFG, "Parse error in %s on line %u : invalid "\
795
                     "port number", filename, line_num);
796 797 798 799 800
              return VS_R_PARSE;
            }
            ports[ul1].flags|=PF_AOBPORT;
          }
        }
801
        VS_log(LOGINFO,CFG," Flag of port %lu set to %u",ul1,\
802
               ports[ul1].flags);
803 804 805 806 807 808 809 810 811


                                        }


<in_switch>hubports({BL}{INT})+         {

        if (!(*s)->nports)
        {
812 813
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u : number of"\
              "ports unknown yet", filename, line_num);
814 815 816 817 818 819 820 821 822 823 824
        }
        {
          unsigned int i;
          unsigned int j;

          for (i=sizeof("hubports")/sizeof(char)-1;i<CFG_yyleng;i+=j)
          {
            ul1=0;
            sscanf(CFG_yytext+i, " %lu%n", &ul1, &j);
            if (!ul1 || ul1>(*s)->nports)
            {
825
              VS_log(LOGERROR, CFG, "Parse error in %s on line %u : invalid "\
826
                     "port number", filename, line_num);
827 828 829 830 831
              return VS_R_PARSE;
            }
            ports[ul1].flags|=PF_HUBPORT;
          }
        }
832
        VS_log(LOGINFO,CFG," Flag of port %lu set to %u",ul1,\
833
               ports[ul1].flags);
834 835 836 837 838


                                        }


839 840 841 842
<in_switch>defecports({BL}{INT})+         {

        if (!(*s)->nports)
        {
843 844
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u : number of"\
              "ports unknown yet", filename, line_num);
845 846 847 848 849 850 851 852 853 854 855
        }
        {
          unsigned int i;
          unsigned int j;

          for (i=sizeof("defecports")/sizeof(char)-1;i<CFG_yyleng;i+=j)
          {
            ul1=0;
            sscanf(CFG_yytext+i, " %lu%n", &ul1, &j);
            if (!ul1 || ul1>(*s)->nports)
            {
856
              VS_log(LOGERROR, CFG, "Parse error in %s on line %u : invalid "\
857 858 859 860 861 862 863 864 865 866 867 868 869
                     "port number", filename, line_num);
              return VS_R_PARSE;
            }
            ports[ul1].flags|=PF_DEFECPORT;
          }
        }
        VS_log(LOGINFO,CFG," Flag of port %lu set to %u",ul1,\
               ports[ul1].flags);


                                        }


870 871 872 873
<in_switch>nobbports({BL}{INT})+        {

        if (!(*s)->nports)
        {
874 875
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u : number of"\
              "ports unknown yet", filename, line_num);
876 877 878 879 880 881 882 883 884 885 886
        }
        {
          unsigned int i;
          unsigned int j;

          for (i=sizeof("nobbports")/sizeof(char)-1;i<CFG_yyleng;i+=j)
          {
            ul1=0;
            sscanf(CFG_yytext+i, " %lu%n", &ul1, &j);
            if (!ul1 || ul1>(*s)->nports)
            {
887
              VS_log(LOGERROR, CFG, "Parse error in %s on line %u : invalid "\
888
                     "port number", filename, line_num);
889 890 891 892 893
              return VS_R_PARSE;
            }
            ports[ul1].flags&=~PF_BBPORT;
          }
        }
894
        VS_log(LOGINFO,CFG," Flag of port %lu set to %u",ul1,\
895
               ports[ul1].flags);
896 897 898 899 900 901 902 903 904


                                        }


<in_switch>noatmports({BL}{INT})+       {

        if (!(*s)->nports)
        {
905 906
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u: number of ports"\
                 " unknown yet", filename, line_num);
907 908 909 910 911 912 913 914 915 916 917
        }
        {
          unsigned int i;
          unsigned int j;

          for (i=sizeof("noatmports")/sizeof(char)-1;i<CFG_yyleng;i+=j)
          {
            ul1=0;
            sscanf(CFG_yytext+i, " %lu%n", &ul1, &j);
            if (!ul1 || ul1>(*s)->nports)
            {
918
              VS_log(LOGERROR, CFG, "Parse error in %s on line %u : invalid "\
919
                     "port number", filename, line_num);
920 921 922 923 924
              return VS_R_PARSE;
            }
            ports[ul1].flags&=~PF_ATMPORT;
          }
        }
925
        VS_log(LOGINFO,CFG," Flag of port %lu set to %u",ul1,\
926
               ports[ul1].flags);
927 928 929 930 931 932 933 934 935


                                        }


<in_switch>noaobports({BL}{INT})+       {

        if (!(*s)->nports)
        {
936 937
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u: number of ports"\
                 " unknown yet", filename, line_num);
938 939 940 941 942 943 944 945 946 947 948
        }
        {
          unsigned int i;
          unsigned int j;

          for (i=sizeof("noaobports")/sizeof(char)-1;i<CFG_yyleng;i+=j)
          {
            ul1=0;
            sscanf(CFG_yytext+i, " %lu%n", &ul1, &j);
            if (!ul1 || ul1>(*s)->nports)
            {
949
              VS_log(LOGERROR, CFG, "Parse error in %s on line %u : invalid "\
950
                     "port number", filename, line_num);
951 952 953 954 955
              return VS_R_PARSE;
            }
            ports[ul1].flags&=~PF_AOBPORT;
          }
        }
956
        VS_log(LOGINFO,CFG," Flag of port %lu set to %u",ul1,\
957
               ports[ul1].flags);
958 959 960 961 962 963 964 965 966


                                        }


<in_switch>nohubports({BL}{INT})+       {

        if (!(*s)->nports)
        {
967 968
          VS_log(LOGERROR, CFG, "Parse error in %s on line %u: number of ports"\
                 " unknown yet", filename, line_num);
969 970 971 972 973 974 975 976 977 978 979
        }
        {
          unsigned int i;
          unsigned int j;

          for (i=sizeof("nohubports")/sizeof(char)-1;i<CFG_yyleng;i+=j)
          {
            ul1=0;
            sscanf(CFG_yytext+i, " %lu%n", &ul1, &j);
            if (!ul1 || ul1>(*s)->nports)
            {
980
              VS_log(LOGERROR, CFG, "Parse error in %s on line %u : invalid "\
981
                     "port number", filename, line_num);
982 983 984 985 986
              return VS_R_PARSE;
            }
            ports[ul1].flags&=~PF_HUBPORT;
          }
        }
987
        VS_log(LOGINFO,CFG," Flag of port %lu set to %u",ul1,\
988
               ports[ul1].flags);
989 990 991 992 993 994


                                        }


<in_switch>end{BL}switch                {
995 996 997

        if ((*s)->community==NULL)
        {
998
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u: community string "\
999
                       "unspecified",filename,line_num);
1000
          ports++;
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
          free(ports);
          free(*s);
          return VS_R_PARSE;
        }
        (*s)->ports=ports;
        ports=NULL;
        s=&((*s)->next);
        BEGIN(INITIAL);
        eof_expected=1;

1011
                                        }
1012 1013 1014 1015 1016


<*>{FB}#.*\n    line_num++;


1017
<*>.|\n         {
1018

1019
        VS_log(LOGERROR,CFG,"Parse error in %s on line %u",filename,line_num);
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
        if (ports+1!=NULL)
          free(ports+1);
        return VS_R_PARSE;

                }

<*><<EOF>>      {

        if (!eof_expected)
        {
1030 1031
          VS_log(LOGERROR,CFG,"Parse error in %s on line %u: unexpected end of"\
                       " file",filename,line_num);
1032 1033 1034 1035
          if (ports+1!=NULL)
            free(ports+1);
          return VS_R_PARSE;
        }
1036
        VS_log(LOGINFO,CFG,"Parsing of %s over, %u lines parsed",filename,\
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
                    line_num);
        return 0;

                }


%%


#include <stdio.h>

void cleanup(struct VS_config *cfg)
{
  unsigned long l;
  struct CFG_SWITCH_TYPE *z;
  void *y;

  if (cfg->chan_map!=NULL)
  {
    for (l=0;(VS_CHANNEL)l<cfg->nchannels;l++)
      if (cfg->chan_map[l].raw_data!=NULL)
        free(cfg->chan_map[l].raw_data);
    free(cfg->chan_map);
  }
  for (z=cfg->switch_types;z!=NULL;)
  {
    if ((z->ports+1)!=NULL)
      free(z->ports+1);
    y=z;
    z=z->next;
    free(y);
  }
}

ERR_CODE CFG_init(struct VS_config *cfg,int argc,char *argv[])
{
  ERR_CODE ret;
  char *filepath=CFG_FILE_PATH;
  unsigned int i;

  for (i=1;i<argc;i++)
    if (argv[i][0]=='-')
      switch (argv[i][1])
      {
        case 'f':
          if (argv[i][2])
            filepath=argv[i]+2;
          else
          {
            i++;
            if (i<argc)
              filepath=argv[i];
            else
            {
1091
              VS_log(LOGERROR,CFG,"Expecting filename after option -f");
1092 1093 1094 1095 1096
              return VS_R_PARSE;
            }
          }
          break;
        default:
1097
          VS_log(LOGERROR,CFG,"Unknown option %s",argv[i]);
1098 1099 1100 1101
          return VS_R_PARSE;
      }
    else
    {
1102
      VS_log(LOGERROR,CFG,"Unknown otpion %s",argv[i]);
1103 1104 1105
      return VS_R_PARSE;
    }
  
1106
  VS_log(LOGINFO,CFG,"Reading configuration file %s...",filepath);
1107 1108 1109
  cfg->nchannels=0;
  cfg->chan_map=NULL;
  cfg->switch_types=NULL;
1110
  cfg->vlanbridge=NULL;
1111 1112 1113 1114 1115 1116 1117 1118
  cfg->vlanbridge_login=NULL;
  cfg->vlanbridge_password=NULL;
  cfg->zwitches=NULL;
  CFG_yyin=fopen(filepath,"r");
  if (CFG_yyin!=NULL)
    ret=CFG_yylex(cfg,CFG_FILE_PATH);
  else
  {
1119
    VS_log(LOGERROR,CFG,"Unable to open %s",filepath);
1120 1121 1122
    return VS_R_FILE;
  }
  if (fclose(CFG_yyin))
1123
    VS_log(LOGERROR,CFG,"An error occured while closing %s, still going on",\
1124 1125 1126 1127
                 filepath);
  if (ret)
    cleanup(cfg);
  else
1128
    VS_log(LOGINFO,CFG,"Setup successfuly terminated");
1129 1130
  return ret;
}