source: rtems/tools/cpu/nios2/ptf.c @ 125e23b

4.115
Last change on this file since 125e23b was 125e23b, checked in by Joel Sherrill <joel.sherrill@…>, on 01/13/15 at 21:40:47

tools/cpu/nios2/ptf.c: Add include to fix warnings

  • Property mode set to 100644
File size: 19.2 KB
Line 
1/*
2 *  Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.org/license/LICENSE.
7 */
8
9#include <stdio.h>
10#include <string.h>
11#include <stdlib.h>
12#include <errno.h>
13#include "ptf.h"
14
15#define PTFPARSER_MAXDEPTH 20
16#define PTFPARSER_NAMEBUFSIZE 1024
17#define PTFPARSER_VALUEBUFSIZE 4096
18
19#define DEBUG_EXPECTATIONS 1
20#define DEBUG_READVALUES 2
21#define DEBUG_FINDER 4
22#define DEBUG 0
23
24struct ptf_parser_state
25{
26  struct ptf *tree;
27  struct ptf *current_in[PTFPARSER_MAXDEPTH];
28  struct ptf *current_item;
29
30  long line;  /* starts with 1, increments whenever a LF (ASCII 10) passes */
31  int section_level; /* starts at 0, incremented at {, decremented at } */
32  char *filename;
33  char name_buffer[PTFPARSER_NAMEBUFSIZE];
34  int name_length;
35  char value_buffer[PTFPARSER_VALUEBUFSIZE];
36  int value_length;
37  struct
38  {
39    unsigned error:1;
40    unsigned escaped:1;
41    unsigned single_quoted:1;
42    unsigned double_quoted:1;
43  } flag;
44
45  enum
46  {
47    section_or_item_specification,
48    more_section_type_or_item_name_chars,
49    whitespace_after_section_specification,
50    whitespace_after_section_or_item_name,
51    whitespace_before_item_value,
52    more_section_name_chars,
53    more_item_value_chars,
54  } expectation;
55};
56
57/***************************************************************************/
58struct ptf *ptf_alloc_item(ptf_item_type t, char *name, char *value)
59{
60  struct ptf *new_item;
61  new_item = (struct ptf *)malloc(sizeof(struct ptf));
62  if(!new_item) return NULL;
63
64  new_item->type = t;
65  new_item->sub = NULL;
66  new_item->next = NULL;
67  new_item->name = NULL;
68  new_item->value = NULL;
69
70  if(name != NULL)
71  {
72    int n = strlen(name);
73    if(n > 0)
74    {
75      new_item->name = (char *)malloc(n + 1);
76      if(new_item->name == NULL)
77      {
78        free(new_item);
79        return NULL;
80      };
81      strcpy(new_item->name, name);
82    }
83  };
84
85  if(value != NULL)
86  {
87    int n = strlen(value);
88    if(n > 0)
89    {
90      new_item->value = (char *)malloc(n + 1);
91      if(new_item->value == NULL)
92      {
93        if(name != NULL) free(new_item->name);
94        free(new_item);
95        return NULL;
96      };
97      strcpy(new_item->value, value);
98    };
99  };
100
101  return new_item;
102}
103
104/***************************************************************************/
105void add_ptf_item(struct ptf_parser_state *state, struct ptf *item)
106{
107   if(state->current_item == NULL)
108   {
109     if(state->section_level > 0)
110       state->current_in[state->section_level-1]->sub = item;
111     else
112       state->tree = item;
113   }
114   else
115     state->current_item->next = item;
116}
117
118
119/***************************************************************************/
120void parse_error(struct ptf_parser_state *state, char *errmsg)
121{
122  fprintf(stderr, "Error while parsing %s (line %lu): %s\n",
123    state->filename, state->line, errmsg);
124
125  state->flag.error = 1;
126}
127
128/***************************************************************************/
129void init_parser(struct ptf_parser_state *state, char *filename)
130{
131  int i;
132
133  state->line = 1;
134  state->flag.error = 0;
135  state->flag.escaped = 0;
136  state->flag.double_quoted = 0;
137  state->flag.single_quoted = 0;
138  state->section_level = 0;
139
140  state->filename = (char *)malloc(strlen(filename)+1);
141  if(state->filename != NULL) strcpy(state->filename, filename);
142
143  state->expectation = section_or_item_specification;
144
145  state->tree = NULL;
146  state->current_item = NULL;
147  for(i=1; i<PTFPARSER_MAXDEPTH; i++) state->current_in[i] = NULL;
148}
149
150/***************************************************************************/
151void ptf_free(struct ptf *ptf)
152{
153  struct ptf *this, *next;
154  for(this = ptf; this != NULL; this = next)
155  {
156    next = this->next;
157    if(this->value != NULL) free(this->value);
158    if(this->name != NULL) free(this->name);
159    if(this->type == section) ptf_free(this->sub);
160    free(this);
161  };
162}
163
164/***************************************************************************/
165void abort_parsing(struct ptf_parser_state *state)
166{
167  if(state->filename != NULL) free(state->filename);
168  ptf_free(state->tree);
169}
170
171/***************************************************************************/
172int add_char_to_buffer(int *len, char *buf, int maxlen, char c)
173{
174  if(*len >= maxlen) return 0;
175
176  buf[(*len)++] = c;
177
178  return 1;
179}
180
181/***************************************************************************/
182void parse_char(struct ptf_parser_state *state, int c)
183{
184  int is_not_quoted;
185  int is_no_space;
186  enum { item_parsed, section_opened, section_closed, none } parser_event;
187
188  switch(c)
189  {
190    case '\\':
191    {
192      if(state->flag.escaped == 0)
193      {
194        state->flag.escaped = 1;
195        return;
196      };
197      break;
198    };
199    case '"':
200    {
201      if(!state->flag.escaped && !state->flag.single_quoted)
202      {
203        state->flag.double_quoted = 1 - state->flag.double_quoted;
204        return;
205      }
206      break;
207    };
208    case '\'':
209    {
210      if(!state->flag.escaped && !state->flag.double_quoted)
211      {
212        state->flag.single_quoted = 1 - state->flag.single_quoted;
213        return;
214      }
215      break;
216    };
217    case '\n':
218    {
219      state->line++;
220      break;
221    };
222    default:
223      break;
224  };
225
226  parser_event = none;
227
228  is_not_quoted = !(state->flag.escaped ||
229    state->flag.single_quoted || state->flag.double_quoted);
230  is_no_space = (!is_not_quoted || !isspace(c));
231  state->flag.escaped = 0;
232
233  switch(state->expectation)
234  {
235    case section_or_item_specification:
236    {
237#if DEBUG&DEBUG_EXPECTATIONS
238      printf("Expectation: section_or_item_specification\n");
239#endif
240
241      if(is_not_quoted && c == '}')
242      {
243        parser_event = section_closed;
244      }
245      else if(is_no_space)
246      {
247        state->name_length = 1;
248        state->name_buffer[0] = c;
249        state->expectation = more_section_type_or_item_name_chars;
250      };
251      break;
252    };
253
254    case more_section_type_or_item_name_chars:
255    {
256#if DEBUG&DEBUG_EXPECTATIONS
257      printf("Expectation: more_section_type_or_item_name_chars\n");
258#endif
259
260      /* Item name is stored in name_buffer */
261      /* Section type is stored in name_buffer */
262      if(is_no_space)
263      {
264        if(!add_char_to_buffer(&state->name_length, state->name_buffer, PTFPARSER_NAMEBUFSIZE, c))
265          parse_error(state, "First word is too long; I expected a shorter section type or item name");
266      }
267      else
268      {
269        state->expectation = whitespace_after_section_or_item_name;
270      }
271      break;
272    };
273
274    case whitespace_after_section_specification:
275    {
276#if DEBUG&DEBUG_EXPECTATIONS
277      printf("Expectation: whitespace_after_section_specification\n");
278#endif
279
280      if(c == '{')
281        parser_event = section_opened;
282      else if(is_no_space)
283        parse_error(state, "Expected section content within brackets {...}");
284      break;
285    };
286
287    case whitespace_after_section_or_item_name:
288    {
289#if DEBUG&DEBUG_EXPECTATIONS
290      printf("Expectation: whitespace_after_section_or_item_name\n");
291#endif
292
293      if(c == '{')
294      {
295        state->value_length = 0;
296        parser_event = section_opened;
297      }
298      else if(c == '=')
299        state->expectation = whitespace_before_item_value;
300      else if(is_no_space)
301      {
302        state->value_length = 1;
303        state->value_buffer[0] = c;
304        state->expectation = more_section_name_chars;
305      };
306      break;
307    };
308
309    case more_section_name_chars:
310    {
311#if DEBUG&DEBUG_EXPECTATIONS
312      printf("Expectation: more_section_name_chars\n");
313#endif
314
315      /* Section name is stored in value_buffer */
316      if(is_no_space)
317      {
318        if(!add_char_to_buffer(&state->value_length, state->value_buffer, PTFPARSER_VALUEBUFSIZE, c))
319          parse_error(state, "Section name is too long");
320      }
321      else
322        state->expectation = whitespace_after_section_specification;
323      break;
324    }
325
326    case whitespace_before_item_value:
327    {
328#if DEBUG&DEBUG_EXPECTATIONS
329      printf("Expectation: whitespace_before_item_value\n");
330#endif
331
332      if(is_not_quoted && c == ';')
333      {
334        state->value_length = 0;
335        parser_event = item_parsed;
336      }
337      else if(is_no_space)
338      {
339        state->value_length = 1;
340        state->value_buffer[0] = c;
341        state->expectation = more_item_value_chars;
342      };
343      break;
344    };
345
346    case more_item_value_chars:
347    {
348#if DEBUG&DEBUG_EXPECTATIONS
349      printf("Expectation: more_item_value_chars\n");
350#endif
351
352      /* Item value is stored in value_buffer */
353      if(is_not_quoted && c == ';')
354        parser_event = item_parsed;
355      else if(is_no_space)
356      {
357        if(!add_char_to_buffer(&state->value_length, state->value_buffer, PTFPARSER_VALUEBUFSIZE, c))
358          parse_error(state, "Item value is too long");
359      }
360      else
361        parser_event = item_parsed;
362      break;
363    }
364
365    default:
366#if DEBUG&DEBUG_EXPECTATIONS
367      printf("Expectation: %d (?)\n", state->expectation);
368#endif
369
370      parse_error(state, "Internal error: Unhandled state of expectation");
371  };
372
373  switch(parser_event)
374  {
375    /* TODO: pointer tuff */
376
377    case item_parsed:
378    {
379      struct ptf *new_item;
380      state->name_buffer[state->name_length] = 0;
381      state->value_buffer[state->value_length] = 0;
382#if DEBUG&DEBUG_READVALUES
383      printf("== Item %s is '%s' ==\n", state->name_buffer, state->value_buffer);
384#endif
385
386      new_item = ptf_alloc_item(item, state->name_buffer, state->value_buffer);
387      if(new_item == NULL)
388      {
389        parse_error(state, "Internal error: "
390            "Could not allocate memory for new item");
391        return;
392      };
393
394      add_ptf_item(state, new_item);
395      state->current_item = new_item;
396      state->expectation = section_or_item_specification;
397
398      break;
399    };
400    case section_opened:
401    {
402      struct ptf *new_section;
403      state->name_buffer[state->name_length] = 0;
404      state->value_buffer[state->value_length] = 0;
405#if DEBUG&DEBUG_READVALUES
406      printf("== New %s section '%s' opened ==\n", state->name_buffer, state->value_buffer);
407#endif
408
409      if(state->section_level >= PTFPARSER_MAXDEPTH-1)
410      {
411        parse_error(state, "Internal error: "
412             "cannot handle sections nested as deep as here.");
413        return;
414      };
415
416      new_section = ptf_alloc_item(section, state->name_buffer, state->value_buffer);
417      if(new_section == NULL)
418      {
419        parse_error(state, "Internal error: "
420            "Could not allocate memory for new section");
421        return;
422      };
423
424      add_ptf_item(state, new_section);
425      state->current_item = NULL;
426      state->current_in[state->section_level] = new_section;
427      state->section_level++;
428
429      state->expectation = section_or_item_specification;
430      break;
431    };
432    case section_closed:
433    {
434      if(state->section_level < 1)
435      {
436        parse_error(state, "Found closing '}' without opening '{' before");
437        return;
438      };
439
440      state->section_level--;
441      state->current_item = state->current_in[state->section_level];
442      state->expectation = section_or_item_specification;
443#if DEBUG&DEBUG_READVALUES
444      printf("-- Closed section --\n");
445#endif
446      break;
447    };
448    default:
449      break;
450  };
451}
452
453/***************************************************************************/
454struct ptf *ptf_parse_file(char *filename)
455{
456  FILE *f;
457  char buffer[1024];
458
459  struct ptf *root;
460  struct ptf_parser_state state;
461
462  if(filename == NULL)
463  {
464    fprintf(stderr, "Internal error: "
465                    "No filename was given to ptf_read()\n");
466    return NULL;
467  };
468
469  f = fopen(filename, "r");
470  if(f == NULL)
471  {
472    perror(filename);
473    return NULL;
474  };
475
476  init_parser(&state, filename);
477
478  while(!feof(f))
479  {
480    size_t r, n;
481
482    if(ferror(f))
483    {
484      perror(filename);
485      abort_parsing(&state);
486      fclose(f);
487      return NULL;
488    };
489
490    n = fread(buffer, 1, 1024, f);
491    for(r=0; r<n && (state.flag.error==0); r++) parse_char(&state, buffer[r]);
492  };
493
494  fclose(f);
495
496  if(state.section_level != 0)
497  {
498    parse_error(&state, "Input file seems to be incomplete, "
499                        "one or more sections are not closed with '}'\n");
500  };
501
502  if(state.flag.error)
503  {
504    abort_parsing(&state);
505    return NULL;
506  };
507
508  return state.tree;
509}
510
511/***************************************************************************/
512
513struct ptf *ptf_concat(struct ptf *a, struct ptf *b)
514{
515  struct ptf *leaf = a;
516
517  if(!a) return b;
518  if(!b) return a;
519
520  for(leaf = a; leaf->next != NULL; leaf = leaf->next);
521  leaf->next = b;
522  return a;
523}
524
525/***************************************************************************/
526
527void ptf_dump_ptf_item(FILE *f, struct ptf_item *pi)
528{
529  int i;
530  fprintf(f, "level=%d in %p\n", pi->level, pi);
531  for(i=pi->level;i>=0;i--)
532  {
533    if(pi->item[i] != NULL)
534    {
535      fprintf(f, "  %d: %s name=%s value=%s\n",
536        i,
537        pi->item[i]->type == item ? "item":"section",
538        pi->item[i]->name,
539        pi->item[i]->value);
540    }
541    else
542    {
543        fprintf(f, "  %d: NULL\n");
544    }
545    fflush(f);
546  }
547}
548
549/***************************************************************************/
550
551void ptf_printf(FILE *s, struct ptf *tree, char *prefix)
552{
553  struct ptf *leaf;
554
555  for(leaf = tree; leaf != NULL; leaf = leaf->next)
556  {
557    switch(leaf->type)
558    {
559      case section:
560      {
561        char *new_prefix;
562        int new_prefix_len;
563        new_prefix_len = strlen(prefix) + strlen(leaf->name) + 2;
564        if(leaf->value != NULL && leaf->value[0] != 0)
565        {
566          new_prefix_len += strlen(leaf->value) + 1;
567        };
568        new_prefix = (char *)malloc(new_prefix_len);
569        strcpy(new_prefix, prefix);
570        strcat(new_prefix, leaf->name);
571        if(leaf->value != NULL && leaf->value[0] != 0)
572        {
573          strcat(new_prefix, ":");
574          strcat(new_prefix, leaf->value);
575        };
576        strcat(new_prefix, "/");
577        fputs(new_prefix, s);
578        fputs("\n", s);
579        ptf_printf(s, leaf->sub, new_prefix);
580        break;
581      };
582
583      case item:
584      {
585        char *c;
586        fputs(prefix, s);
587        fputs(leaf->name, s);
588        fputs(" = \"", s);
589        if(leaf->value == NULL)
590        {
591          fputs("(NULL)", s);
592        }
593        else
594        {
595          for(c=leaf->value; *c; c++)
596          {
597            if(*c=='\\' || *c=='"') putc('\\', s);
598            putc(*c, s);
599          };
600        }
601        fprintf(s, "\"\n");
602        break;
603      };
604
605      default:
606        break;
607    };
608  };
609}
610
611/***************************************************************************/
612
613int ptf_advance_one(struct ptf_item *item)
614{
615  int d;
616  struct ptf *leaf;
617
618  d = item->level;
619  leaf = item->item[d];
620
621  if(leaf != NULL)
622  {
623    if(leaf->type == section && leaf->sub != NULL)
624    {
625      if(item->level >= MAX_SECTION_NESTING-1)
626      {
627        /* raise an error? hm, for now we silently ignore the subtree */
628      }
629      else
630      {
631        d++;
632        item->item[d] = leaf->sub;
633        item->level = d;
634        return 0;
635      }
636    }
637    item->item[item->level] = leaf->next;
638  };
639
640  while(item->item[d] == NULL)
641  {
642    if(d == 0)
643    {
644      item->level = 0;
645      item->item[0] = NULL;
646      errno = ENOENT;
647      return -1;
648    }
649    d --;
650    leaf = item->item[d];
651    if(leaf != NULL) item->item[d] = leaf->next;
652  };
653
654  item->level = d;
655  return 0;
656}
657
658/***************************************************************************/
659
660int ptf_advance_until(
661  struct ptf_item *item,
662  ptf_item_type ttype,
663  char *name,
664  char *value)
665{
666  int r;
667  struct ptf *leaf;
668
669  do
670  {
671    leaf = item->item[item->level];
672#if DEBUG&DEBUG_FINDER
673    printf(" Does %s/%s match %s/%s?\n", leaf->name, leaf->value, name, value);
674#endif
675
676    if(leaf->type == ttype)
677    {
678      if(name == NULL)
679      {
680        if(value == NULL)
681        {
682          return 0; /* got it (any value) */
683        }
684        else if (leaf->value != NULL)
685        {
686          if(strcmp(leaf->value, value) == 0) return 0; /* got it */
687        }
688      }
689      else if(leaf->name != NULL)
690      {
691        if(strcmp(leaf->name, name) == 0)
692        {
693          if(value == NULL)
694          {
695            return 0; /* got it (any value) */
696          }
697          else if(leaf->value != NULL)
698          {
699            if(strcmp(leaf->value, value) == 0) return 0; /* got it */
700          }
701        }
702      }
703    };
704    r = ptf_advance_one(item);
705
706  } while(r == 0);
707
708  return r;
709}
710
711/***************************************************************************/
712
713struct ptf *ptf_find(
714  struct ptf *tree,
715  struct ptf_item *item,
716  ptf_item_type ttype,
717  char *name,
718  char *value)
719{
720  int r;
721
722  if(item == NULL) { errno = EINVAL; return NULL; };
723  if(tree == NULL) { errno = ENOENT; return NULL; };
724
725  item->level = 0;
726  item->item[0] = tree;
727
728  if(ptf_advance_until(item, ttype, name, value) != 0) return NULL;
729
730  r = item->level;
731  item->level++; /* To match ptf_match */
732  return item->item[r];
733}
734
735/***************************************************************************/
736
737struct ptf *ptf_next(
738  struct ptf_item *item,
739  ptf_item_type ttype,
740  char *name,
741  char *value)
742{
743  int r;
744  struct ptf *leaf;
745
746  if(item == NULL) { errno = EINVAL; return NULL; };
747
748  if(item->level < 1) return NULL;
749  item->level--; /* To match ptf_match */
750
751  r = ptf_advance_one(item);
752
753  if(r == 0) r = ptf_advance_until(item, ttype, name, value);
754
755  if(r != 0) return NULL;
756
757  r = item->level;
758  item->level++; /* To match ptf_match */
759  return item->item[r];
760}
761
762/***************************************************************************/
763
764int ptf_match(
765  struct ptf *const ptf,
766  struct ptf_item *const match,
767  const ptf_match_action action,
768  void *arg)
769{
770    int count;
771    struct ptf *p;
772    struct ptf_item pi;
773
774    p = ptf;
775    count = 0;
776    pi.level = 0;
777
778    while(p != NULL)
779    {
780        ptf_item_type mtype = match->item[pi.level]->type;
781        char *mname = match->item[pi.level]->name;
782        char *mvalue = match->item[pi.level]->value;
783
784#if DEBUG&DEBUG_FINDER
785        printf("Looking for %s/%s, checking %s/%s\n",
786          mname, mvalue, p->name, p->value);
787#endif
788
789        if(mtype == p->type &&
790           (mname==NULL || p->name==NULL || strcmp(mname, p->name)==0) &&
791           (mvalue==NULL || p->value==NULL || strcmp(mvalue, p->value)==0))
792        {
793            pi.item[pi.level] = p;
794
795            if(pi.level == match->level - 1)
796            {
797                if(action != NULL) action(&pi, arg);
798                p = p->next;
799                count++;
800            }
801            else
802            {
803                if(p->sub != NULL && pi.level < MAX_SECTION_NESTING-1)
804                {
805                    pi.item[pi.level] = p;
806                    pi.level++;
807                    p = p->sub;
808                }
809                else
810                {
811                    p = p->next;
812                };
813            };
814        }
815        else
816        {
817            p = p->next;
818        };
819
820        while(p == NULL && pi.level > 0)
821        {
822            pi.level--;
823            p = pi.item[pi.level]->next;
824        };
825    };
826    return count;
827}
828
829/***************************************************************************/
830
831char *ptf_defused_name(char *orig_name)
832{
833  int i,j;
834  char *s = (char *)malloc(1+strlen(orig_name));
835
836  if(!s) return NULL;
837
838  for(i=j=0;orig_name[i];i++)
839  {
840    if(!isalnum(orig_name[i]))
841    {
842      if(j>0) if(s[j-1]!='_') s[j++]='_';
843    }
844    else
845    {
846      s[j++] = toupper(orig_name[i]);
847    };
848  };
849  s[j] = 0;
850  return s;
851}
852
Note: See TracBrowser for help on using the repository browser.