source: rtems/tools/cpu/nios2/ptf.c @ 037e1639

4.104.114.84.95
Last change on this file since 037e1639 was 037e1639, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 9, 2006 at 9:05:32 PM

2006-08-09 Kolja Waschk <waschk@…>

  • configure.ac: New port to Altera NIOS II.
  • nios2/.cvsignore, nios2/Makefile.am, nios2/README, nios2/bridges.c, nios2/bridges.h, nios2/clocks.c, nios2/clocks.h, nios2/configure.ac, nios2/devices.c, nios2/devices.h, nios2/nios2gen.c, nios2/output.c, nios2/output.h, nios2/ptf.c, nios2/ptf.h: New files.
  • Property mode set to 100644
File size: 18.3 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.com/license/LICENSE.
7 *
8 *  $Id$
9 */
10
11#include <stdio.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
513void ptf_printf(FILE *s, struct ptf *tree, char *prefix)
514{
515  struct ptf *leaf;
516
517  for(leaf = tree; leaf != NULL; leaf = leaf->next)
518  {
519    switch(leaf->type)
520    {
521      case section:
522      {
523        char *new_prefix;
524        int new_prefix_len;
525        new_prefix_len = strlen(prefix) + strlen(leaf->name) + 2;
526        if(leaf->value != NULL && leaf->value[0] != 0)
527        {
528          new_prefix_len += strlen(leaf->value) + 1;
529        };
530        new_prefix = (char *)malloc(new_prefix_len);
531        strcpy(new_prefix, prefix);
532        strcat(new_prefix, leaf->name);
533        if(leaf->value != NULL && leaf->value[0] != 0)
534        {
535          strcat(new_prefix, "_");
536          strcat(new_prefix, leaf->value);
537        };
538        strcat(new_prefix, "/");
539        fputs(new_prefix, s);
540        fputs("\r\n", s);
541        ptf_printf(s, leaf->sub, new_prefix);
542        break;
543      };
544
545      case item:
546      {
547        char *c;
548        fputs(prefix, s);
549        fputs(leaf->name, s);
550        fputs(" = \"", s);
551        for(c=leaf->value; *c; c++)
552        {
553          if(*c=='\\' || *c=='"') putc('\\', s);
554          putc(*c, s);
555        };
556        fprintf(s, "\"\r\n");
557        break;
558      };
559
560      default:
561        break;
562    };
563  };
564}
565
566/***************************************************************************/
567
568int ptf_advance_one(struct ptf_item *item)
569{
570  int d;
571  struct ptf *leaf;
572
573  d = item->level;
574  leaf = item->item[d];
575
576  if(leaf != NULL)
577  {
578    if(leaf->type == section && leaf->sub != NULL)
579    {
580      if(item->level >= MAX_SECTION_NESTING-1)
581      {
582        /* raise an error? hm, for now we silently ignore the subtree */
583      }
584      else
585      {
586        d++;
587        item->item[d] = leaf->sub;
588        item->level = d;
589        return 0;
590      }
591    }
592    item->item[item->level] = leaf->next;
593  };
594
595  while(item->item[d] == NULL)
596  {
597    if(d == 0)
598    {
599      item->level = 0;
600      item->item[0] = NULL;
601      errno = ENOENT;
602      return -1;
603    }
604    d --;
605    leaf = item->item[d];
606    if(leaf != NULL) item->item[d] = leaf->next;
607  };
608
609  item->level = d;
610  return 0;
611}
612
613/***************************************************************************/
614
615int ptf_advance_until(
616  struct ptf_item *item,
617  ptf_item_type ttype,
618  char *name,
619  char *value)
620{
621  int r;
622  struct ptf *leaf;
623
624  do
625  {
626    leaf = item->item[item->level];
627#if DEBUG&DEBUG_FINDER
628    printf(" Does %s/%s match %s/%s?\n", leaf->name, leaf->value, name, value);
629#endif
630
631    if(leaf->type == ttype)
632    {
633      if(name == NULL)
634      {
635        if(value == NULL)
636        {
637          return 0; /* got it (any value) */
638        }
639        else if (leaf->value != NULL)
640        {
641          if(strcmp(leaf->value, value) == 0) return 0; /* got it */
642        }
643      } 
644      else if(leaf->name != NULL)
645      {
646        if(strcmp(leaf->name, name) == 0)
647        {
648          if(value == NULL)
649          {
650            return 0; /* got it (any value) */
651          }
652          else if(leaf->value != NULL)
653          {
654            if(strcmp(leaf->value, value) == 0) return 0; /* got it */
655          }
656        }
657      }
658    };
659    r = ptf_advance_one(item);
660
661  } while(r == 0);
662
663  return r;
664}
665
666/***************************************************************************/
667
668struct ptf *ptf_find(
669  struct ptf *tree, 
670  struct ptf_item *item,
671  ptf_item_type ttype,
672  char *name,
673  char *value)
674{
675  int r;
676
677  if(item == NULL) { errno = EINVAL; return NULL; };
678  if(tree == NULL) { errno = ENOENT; return NULL; };
679
680  item->level = 0;
681  item->item[0] = tree;
682
683  if(ptf_advance_until(item, ttype, name, value) != 0) return NULL;
684
685  r = item->level;
686  item->level++; /* To match ptf_match */
687  return item->item[r];
688}
689
690/***************************************************************************/
691
692struct ptf *ptf_next(
693  struct ptf_item *item,
694  ptf_item_type ttype,
695  char *name,
696  char *value)
697{
698  int r;
699  struct ptf *leaf;
700
701  if(item == NULL) { errno = EINVAL; return NULL; };
702
703  if(item->level < 1) return NULL;
704  item->level--; /* To match ptf_match */
705
706  r = ptf_advance_one(item);
707
708  if(r == 0) r = ptf_advance_until(item, ttype, name, value);
709
710  if(r != 0) return NULL;
711
712  r = item->level;
713  item->level++; /* To match ptf_match */
714  return item->item[r];
715}
716
717/***************************************************************************/
718
719int ptf_match(
720  struct ptf *const ptf,
721  struct ptf_item *const match, 
722  const ptf_match_action action, 
723  void *arg)
724{
725    int count;
726    struct ptf *p;
727    struct ptf_item pi;
728
729    p = ptf;
730    count = 0;
731    pi.level = 0;
732
733    while(p != NULL)
734    {
735        ptf_item_type mtype = match->item[pi.level]->type;
736        char *mname = match->item[pi.level]->name;
737        char *mvalue = match->item[pi.level]->value;
738
739#if DEBUG&DEBUG_FINDER
740        printf("Looking for %s/%s, checking %s/%s\n",
741          mname, mvalue, p->name, p->value);
742#endif
743
744        if(mtype == p->type &&
745           (mname==NULL || p->name==NULL || strcmp(mname, p->name)==0) && 
746           (mvalue==NULL || p->value==NULL || strcmp(mvalue, p->value)==0))
747        {
748            pi.item[pi.level] = p;
749
750            if(pi.level == match->level - 1)
751            {
752                if(action != NULL) action(&pi, arg);
753                p = p->next;
754                count++;
755            }
756            else
757            {
758                if(p->sub != NULL && pi.level < MAX_SECTION_NESTING-1)
759                {
760                    pi.item[pi.level] = p;
761                    pi.level++;
762                    p = p->sub;
763                }
764                else
765                {
766                    p = p->next;
767                };
768            };
769        }
770        else
771        {
772            p = p->next;
773        };
774
775        while(p == NULL && pi.level > 0)
776        {
777            pi.level--;
778            p = pi.item[pi.level]->next;
779        };
780    };
781    return count;
782}
783
784/***************************************************************************/
785
786char *ptf_defused_name(char *orig_name)
787{
788  int i,j;
789  char *s = (char *)malloc(1+strlen(orig_name));
790
791  if(!s) return NULL;
792
793  for(i=j=0;orig_name[i];i++)
794  {
795    if(!isalnum(orig_name[i]))
796    {
797      if(j>0) if(s[j-1]!='_') s[j++]='_';
798    }
799    else
800    {
801      s[j++] = toupper(orig_name[i]);
802    };
803  };
804  s[j] = 0;
805  return s;
806}
807
Note: See TracBrowser for help on using the repository browser.