]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/lex.c
Fix of case from Fileset to FileSet for compatibility with mysql.
[bacula/bacula] / bacula / src / lib / lex.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation plus additions
11    that are listed in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * Lexical scanner for Bacula configuration file
30  *
31  *   Kern Sibbald, 2000
32  *
33  *   Version $Id$
34  *
35  */
36
37 #include "bacula.h"
38 #include "lex.h"
39
40 extern int debug_level;
41
42 /* Debug level for this source file */
43 static const int dbglvl = 5000;
44
45 /*
46  * Scan to "logical" end of line. I.e. end of line,
47  *   or semicolon, but stop on T_EOB (same as end of
48  *   line except it is not eaten).
49  */
50 void scan_to_eol(LEX *lc)
51 {
52    int token;
53    Dmsg0(dbglvl, "start scan to eof\n");
54    while ((token = lex_get_token(lc, T_ALL)) != T_EOL) {
55       if (token == T_EOB) {
56          lex_unget_char(lc);
57          return;
58       }
59    }
60 }
61
62 /*
63  * Get next token, but skip EOL
64  */
65 int scan_to_next_not_eol(LEX * lc)
66 {
67    int token;
68    do {
69       token = lex_get_token(lc, T_ALL);
70    } while (token == T_EOL);
71    return token;
72 }
73
74 /*
75  * Format a scanner error message
76  */
77 static void s_err(const char *file, int line, LEX *lc, const char *msg, ...)
78 {
79    va_list arg_ptr;
80    char buf[MAXSTRING];
81    char more[MAXSTRING];
82
83    va_start(arg_ptr, msg);
84    bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
85    va_end(arg_ptr);
86
87    if (lc->err_type == 0) {     /* M_ERROR_TERM by default */
88       lc->err_type = M_ERROR_TERM;
89    }
90
91    if (lc->line_no > lc->begin_line_no) {
92       bsnprintf(more, sizeof(more),
93                 _("Problem probably begins at line %d.\n"), lc->begin_line_no);
94    } else {
95       more[0] = 0;
96    }  
97    if (lc->line_no > 0) {
98       e_msg(file, line, lc->err_type, 0, _("Config error: %s\n"
99 "            : line %d, col %d of file %s\n%s\n%s"),
100          buf, lc->line_no, lc->col_no, lc->fname, lc->line, more);
101    } else {
102       e_msg(file, line, lc->err_type, 0, _("Config error: %s\n"), buf);
103    }
104 }
105
106 void lex_set_default_error_handler(LEX *lf)
107 {
108    lf->scan_error = s_err;
109 }
110
111 /*
112  * Set err_type used in error_handler
113  * return the old value
114  */
115 int lex_set_error_handler_error_type(LEX *lf, int err_type)
116 {
117    int old = lf->err_type;
118    lf->err_type = err_type;
119    return old;
120 }
121
122 /*
123  * Free the current file, and retrieve the contents
124  * of the previous packet if any.
125  */
126 LEX *lex_close_file(LEX *lf)
127 {
128    LEX *of;
129
130    if (lf == NULL) {
131       Emsg0(M_ABORT, 0, _("Close of NULL file\n"));
132    }
133    Dmsg1(dbglvl, "Close lex file: %s\n", lf->fname);
134
135    of = lf->next;
136    if (lf->bpipe) {
137       close_bpipe(lf->bpipe);
138       lf->bpipe = NULL;
139    } else {
140       fclose(lf->fd);
141    }
142    Dmsg1(dbglvl, "Close cfg file %s\n", lf->fname);
143    free(lf->fname);
144    if (of) {
145       of->options = lf->options;      /* preserve options */
146       memcpy(lf, of, sizeof(LEX));
147       Dmsg1(dbglvl, "Restart scan of cfg file %s\n", of->fname);
148    } else {
149       of = lf;
150       lf = NULL;
151    }
152    free(of);
153    return lf;
154 }
155
156 /*
157  * Open a new configuration file. We push the
158  * state of the current file (lf) so that we
159  * can do includes.  This is a bit of a hammer.
160  * Instead of passing back the pointer to the
161  * new packet, I simply replace the contents
162  * of the caller's packet with the new packet,
163  * and link the contents of the old packet into
164  * the next field.
165  *
166  */
167 LEX *lex_open_file(LEX *lf, const char *filename, LEX_ERROR_HANDLER *scan_error)
168
169 {
170    LEX *nf;
171    FILE *fd;
172    BPIPE *bpipe = NULL;
173    char *fname = bstrdup(filename);
174
175
176    if (fname[0] == '|') {
177       if ((bpipe = open_bpipe(fname, 0, "rb")) == NULL) {
178          free(fname);
179          return NULL;
180       }
181       fd = bpipe->rfd;
182    } else if ((fd = fopen(fname, "rb")) == NULL) {
183       free(fname);
184       return NULL;
185    }
186    Dmsg1(400, "Open config file: %s\n", fname);
187    nf = (LEX *)malloc(sizeof(LEX));
188    if (lf) {
189       memcpy(nf, lf, sizeof(LEX));
190       memset(lf, 0, sizeof(LEX));
191       lf->next = nf;                  /* if have lf, push it behind new one */
192       lf->options = nf->options;      /* preserve user options */
193    } else {
194       lf = nf;                        /* start new packet */
195       memset(lf, 0, sizeof(LEX));
196       lex_set_error_handler_error_type(lf, M_ERROR_TERM);
197    }
198    if (scan_error) {
199       lf->scan_error = scan_error;
200    } else {
201       lex_set_default_error_handler(lf);
202    }
203    lf->fd = fd;
204    lf->bpipe = bpipe;
205    lf->fname = fname;
206    lf->state = lex_none;
207    lf->ch = L_EOL;
208    Dmsg1(dbglvl, "Return lex=%x\n", lf);
209    return lf;
210 }
211
212 /*
213  * Get the next character from the input.
214  *  Returns the character or
215  *    L_EOF if end of file
216  *    L_EOL if end of line
217  */
218 int lex_get_char(LEX *lf)
219 {
220    if (lf->ch == L_EOF) {
221       Emsg0(M_ABORT, 0, _("get_char: called after EOF\n"));
222    }
223    if (lf->ch == L_EOL) {
224       if (bfgets(lf->line, MAXSTRING, lf->fd) == NULL) {
225          lf->ch = L_EOF;
226          if (lf->next) {
227             lex_close_file(lf);
228          }
229          return lf->ch;
230       }
231       lf->line_no++;
232       lf->col_no = 0;
233       Dmsg2(1000, "fget line=%d %s", lf->line_no, lf->line);
234    }
235    lf->ch = (uint8_t)lf->line[lf->col_no];
236    if (lf->ch == 0) {
237       lf->ch = L_EOL;
238    } else {
239       lf->col_no++;
240    }
241    Dmsg2(dbglvl, "lex_get_char: %c %d\n", lf->ch, lf->ch);
242    return lf->ch;
243 }
244
245 void lex_unget_char(LEX *lf)
246 {
247    if (lf->ch == L_EOL) {
248       lf->ch = 0;                     /* End of line, force read of next one */
249    } else {
250       lf->col_no--;                   /* Backup to re-read char */
251    }
252
253 }
254
255
256 /*
257  * Add a character to the current string
258  */
259 static void add_str(LEX *lf, int ch)
260 {
261    if (lf->str_len >= MAXSTRING-3) {
262       Emsg3(M_ERROR_TERM, 0, _(
263            _("Config token too long, file: %s, line %d, begins at line %d\n")),
264              lf->fname, lf->line_no, lf->begin_line_no);
265    }
266    lf->str[lf->str_len++] = ch;
267    lf->str[lf->str_len] = 0;
268 }
269
270 /*
271  * Begin the string
272  */
273 static void begin_str(LEX *lf, int ch)
274 {
275    lf->str_len = 0;
276    lf->str[0] = 0;
277    if (ch != 0) {
278       add_str(lf, ch);
279    }
280    lf->begin_line_no = lf->line_no;   /* save start string line no */
281 }
282
283 #ifdef DEBUG
284 static const char *lex_state_to_str(int state)
285 {
286    switch (state) {
287    case lex_none:          return _("none");
288    case lex_comment:       return _("comment");
289    case lex_number:        return _("number");
290    case lex_ip_addr:       return _("ip_addr");
291    case lex_identifier:    return _("identifier");
292    case lex_string:        return _("string");
293    case lex_quoted_string: return _("quoted_string");
294    default:                return "??????";
295    }
296 }
297 #endif
298
299 /*
300  * Convert a lex token to a string
301  * used for debug/error printing.
302  */
303 const char *lex_tok_to_str(int token)
304 {
305    switch(token) {
306    case L_EOF:             return "L_EOF";
307    case L_EOL:             return "L_EOL";
308    case T_NONE:            return "T_NONE";
309    case T_NUMBER:          return "T_NUMBER";
310    case T_IPADDR:          return "T_IPADDR";
311    case T_IDENTIFIER:      return "T_IDENTIFIER";
312    case T_UNQUOTED_STRING: return "T_UNQUOTED_STRING";
313    case T_QUOTED_STRING:   return "T_QUOTED_STRING";
314    case T_BOB:             return "T_BOB";
315    case T_EOB:             return "T_EOB";
316    case T_EQUALS:          return "T_EQUALS";
317    case T_ERROR:           return "T_ERROR";
318    case T_EOF:             return "T_EOF";
319    case T_COMMA:           return "T_COMMA";
320    case T_EOL:             return "T_EOL";
321    default:                return "??????";
322    }
323 }
324
325 static uint32_t scan_pint(LEX *lf, char *str)
326 {
327    int64_t val = 0;
328    if (!is_a_number(str)) {
329       scan_err1(lf, _("expected a positive integer number, got: %s"), str);
330       /* NOT REACHED */
331    } else {
332       errno = 0;
333       val = str_to_int64(str);
334       if (errno != 0 || val < 0) {
335          scan_err1(lf, _("expected a positive integer number, got: %s"), str);
336          /* NOT REACHED */
337       }
338    }
339    return (uint32_t)val;
340 }
341
342 /*
343  *
344  * Get the next token from the input
345  *
346  */
347 int
348 lex_get_token(LEX *lf, int expect)
349 {
350    int ch;
351    int token = T_NONE;
352    bool esc_next = false;
353    int unicode_count = 0;
354
355    Dmsg0(dbglvl, "enter lex_get_token\n");
356    while (token == T_NONE) {
357       ch = lex_get_char(lf);
358       switch (lf->state) {
359       case lex_none:
360          Dmsg2(dbglvl, "Lex state lex_none ch=%d,%x\n", ch, ch);
361          if (B_ISSPACE(ch))
362             break;
363          if (B_ISALPHA(ch)) {
364             if (lf->options & LOPT_NO_IDENT || lf->options & LOPT_STRING) {
365                lf->state = lex_string;
366             } else {
367                lf->state = lex_identifier;
368             }
369             begin_str(lf, ch);
370             break;
371          }
372          if (B_ISDIGIT(ch)) {
373             if (lf->options & LOPT_STRING) {
374                lf->state = lex_string;
375             } else {
376                lf->state = lex_number;
377             }
378             begin_str(lf, ch);
379             break;
380          }
381          Dmsg0(dbglvl, "Enter lex_none switch\n");
382          switch (ch) {
383          case L_EOF:
384             token = T_EOF;
385             Dmsg0(dbglvl, "got L_EOF set token=T_EOF\n");
386             break;
387          case '#':
388             lf->state = lex_comment;
389             break;
390          case '{':
391             token = T_BOB;
392             begin_str(lf, ch);
393             break;
394          case '}':
395             token = T_EOB;
396             begin_str(lf, ch);
397             break;
398          case '"':
399             lf->state = lex_quoted_string;
400             begin_str(lf, 0);
401             break;
402          case '=':
403             token = T_EQUALS;
404             begin_str(lf, ch);
405             break;
406          case ',':
407             token = T_COMMA;
408             begin_str(lf, ch);
409             break;
410          case ';':
411             if (expect != T_SKIP_EOL) {
412                token = T_EOL;      /* treat ; like EOL */
413             }
414             break;
415          case L_EOL:
416             Dmsg0(dbglvl, "got L_EOL set token=T_EOL\n");
417             if (expect != T_SKIP_EOL) {
418                token = T_EOL;
419             }
420             break;
421          case '@':
422             lf->state = lex_include;
423             begin_str(lf, 0);
424             break;
425          case 0xEF:
426             if (lf->line_no != 1 || lf->col_no != 1)
427             {
428                lf->state = lex_string;
429                begin_str(lf, ch);
430                break;
431             }
432             lf->state = lex_unicode_mark;
433             unicode_count = 1;
434             break;
435          default:
436             lf->state = lex_string;
437             begin_str(lf, ch);
438             break;
439          }
440          break;
441       case lex_comment:
442          Dmsg1(dbglvl, "Lex state lex_comment ch=%x\n", ch);
443          if (ch == L_EOL) {
444             lf->state = lex_none;
445             if (expect != T_SKIP_EOL) {
446                token = T_EOL;
447             }
448          } else if (ch == L_EOF) {
449             token = T_ERROR;
450          }
451          break;
452       case lex_number:
453          Dmsg2(dbglvl, "Lex state lex_number ch=%x %c\n", ch, ch);
454          if (ch == L_EOF) {
455             token = T_ERROR;
456             break;
457          }
458          /* Might want to allow trailing specifications here */
459          if (B_ISDIGIT(ch)) {
460             add_str(lf, ch);
461             break;
462          }
463
464          /* A valid number can be terminated by the following */
465          if (B_ISSPACE(ch) || ch == L_EOL || ch == ',' || ch == ';') {
466             token = T_NUMBER;
467             lf->state = lex_none;
468          } else {
469             lf->state = lex_string;
470          }
471          lex_unget_char(lf);
472          break;
473       case lex_ip_addr:
474          if (ch == L_EOF) {
475             token = T_ERROR;
476             break;
477          }
478          Dmsg1(dbglvl, "Lex state lex_ip_addr ch=%x\n", ch);
479          break;
480       case lex_string:
481          Dmsg1(dbglvl, "Lex state lex_string ch=%x\n", ch);
482          if (ch == L_EOF) {
483             token = T_ERROR;
484             break;
485          }
486          if (ch == '\n' || ch == L_EOL || ch == '=' || ch == '}' || ch == '{' ||
487              ch == '\r' || ch == ';' || ch == ',' || ch == '#' || (B_ISSPACE(ch)) ) {
488             lex_unget_char(lf);
489             token = T_UNQUOTED_STRING;
490             lf->state = lex_none;
491             break;
492          }
493          add_str(lf, ch);
494          break;
495       case lex_identifier:
496          Dmsg2(dbglvl, "Lex state lex_identifier ch=%x %c\n", ch, ch);
497          if (B_ISALPHA(ch)) {
498             add_str(lf, ch);
499             break;
500          } else if (B_ISSPACE(ch)) {
501             break;
502          } else if (ch == '\n' || ch == L_EOL || ch == '=' || ch == '}' || ch == '{' ||
503                     ch == '\r' || ch == ';' || ch == ','   || ch == '"' || ch == '#') {
504             lex_unget_char(lf);
505             token = T_IDENTIFIER;
506             lf->state = lex_none;
507             break;
508          } else if (ch == L_EOF) {
509             token = T_ERROR;
510             lf->state = lex_none;
511             begin_str(lf, ch);
512             break;
513          }
514          /* Some non-alpha character => string */
515          lf->state = lex_string;
516          add_str(lf, ch);
517          break;
518       case lex_quoted_string:
519          Dmsg2(dbglvl, "Lex state lex_quoted_string ch=%x %c\n", ch, ch);
520          if (ch == L_EOF) {
521             token = T_ERROR;
522             break;
523          }
524          if (ch == L_EOL) {
525             esc_next = false;
526             break;
527          }
528          if (esc_next) {
529             add_str(lf, ch);
530             esc_next = false;
531             break;
532          }
533          if (ch == '\\') {
534             esc_next = true;
535             break;
536          }
537          if (ch == '"') {
538             token = T_QUOTED_STRING;
539             lf->state = lex_none;
540             break;
541          }
542          add_str(lf, ch);
543          break;
544       case lex_include:            /* scanning a filename */
545          if (ch == L_EOF) {
546             token = T_ERROR;
547             break;
548          }
549          if (B_ISSPACE(ch) || ch == '\n' || ch == L_EOL || ch == '}' || ch == '{' ||
550              ch == ';' || ch == ','   || ch == '"' || ch == '#') {
551             /* Keep the original LEX so we can print an error if the included file can't be opened. */
552             LEX* lfori = lf;
553             
554             lf->state = lex_none;
555             lf = lex_open_file(lf, lf->str, lf->scan_error);
556             if (lf == NULL) {
557                berrno be;
558                scan_err2(lfori, _("Cannot open included config file %s: %s\n"),
559                   lfori->str, be.strerror());
560                return T_ERROR;
561             }
562             break;
563          }
564          add_str(lf, ch);
565          break;
566       case lex_unicode_mark:
567          if (ch == L_EOF) {
568             token = T_ERROR;
569             break;
570          }
571          unicode_count++;
572          if (unicode_count == 2) {
573             if (ch != 0xBB) {
574                token = T_ERROR;
575                break;
576             }
577          } else if (unicode_count == 3) {
578             if (ch != 0xBF) {
579                token = T_ERROR;
580                break;
581             }
582             token = T_UNICODE_MARK;
583             lf->state = lex_none;
584             break;
585          }
586          break;
587       }
588       Dmsg4(dbglvl, "ch=%d state=%s token=%s %c\n", ch, lex_state_to_str(lf->state),
589         lex_tok_to_str(token), ch);
590    }
591    Dmsg2(dbglvl, "lex returning: line %d token: %s\n", lf->line_no, lex_tok_to_str(token));
592    lf->token = token;
593
594    /*
595     * Here is where we check to see if the user has set certain
596     *  expectations (e.g. 32 bit integer). If so, we do type checking
597     *  and possible additional scanning (e.g. for range).
598     */
599    switch (expect) {
600    case T_PINT32:
601       lf->pint32_val = scan_pint(lf, lf->str);
602       lf->pint32_val2 = lf->pint32_val;
603       token = T_PINT32;
604       break;
605
606    case T_PINT32_RANGE:
607       if (token == T_NUMBER) {
608          lf->pint32_val = scan_pint(lf, lf->str);
609          lf->pint32_val2 = lf->pint32_val;
610          token = T_PINT32;
611       } else {
612          char *p = strchr(lf->str, '-');
613          if (!p) {
614             scan_err2(lf, _("expected an integer or a range, got %s: %s"),
615                lex_tok_to_str(token), lf->str);
616             token = T_ERROR;
617             break;
618          }
619          *p++ = 0;                       /* terminate first half of range */
620          lf->pint32_val  = scan_pint(lf, lf->str);
621          lf->pint32_val2 = scan_pint(lf, p);
622          token = T_PINT32_RANGE;
623       }
624       break;
625
626    case T_INT32:
627       if (token != T_NUMBER || !is_a_number(lf->str)) {
628          scan_err2(lf, _("expected an integer number, got %s: %s"),
629                lex_tok_to_str(token), lf->str);
630          token = T_ERROR;
631          break;
632       }
633       errno = 0;
634       lf->int32_val = (int32_t)str_to_int64(lf->str);
635       if (errno != 0) {
636          scan_err2(lf, _("expected an integer number, got %s: %s"),
637                lex_tok_to_str(token), lf->str);
638          token = T_ERROR;
639       } else {
640          token = T_INT32;
641       }
642       break;
643
644    case T_INT64:
645       Dmsg2(dbglvl, "int64=:%s: %f\n", lf->str, strtod(lf->str, NULL));
646       if (token != T_NUMBER || !is_a_number(lf->str)) {
647          scan_err2(lf, _("expected an integer number, got %s: %s"),
648                lex_tok_to_str(token), lf->str);
649          token = T_ERROR;
650          break;
651       }
652       errno = 0;
653       lf->int64_val = str_to_int64(lf->str);
654       if (errno != 0) {
655          scan_err2(lf, _("expected an integer number, got %s: %s"),
656                lex_tok_to_str(token), lf->str);
657          token = T_ERROR;
658       } else {
659          token = T_INT64;
660       }
661       break;
662
663    case T_NAME:
664       if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
665          scan_err2(lf, _("expected a name, got %s: %s"),
666                lex_tok_to_str(token), lf->str);
667          token = T_ERROR;
668       } else if (lf->str_len > MAX_RES_NAME_LENGTH) {
669          scan_err3(lf, _("name %s length %d too long, max is %d\n"), lf->str,
670             lf->str_len, MAX_RES_NAME_LENGTH);
671          token = T_ERROR;
672       }
673       break;
674
675    case T_STRING:
676       if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
677          scan_err2(lf, _("expected a string, got %s: %s"),
678                lex_tok_to_str(token), lf->str);
679          token = T_ERROR;
680       } else {
681          token = T_STRING;
682       }
683       break;
684
685
686    default:
687       break;                          /* no expectation given */
688    }
689    lf->token = token;                 /* set possible new token */
690    return token;
691 }