📄 hw-tree.c
字号:
}/* count the number of entries */static intcount_entries (struct hw *current, const char *property_name, const char *property_value, int modulo){ const char *chp = property_value; int nr_entries = 0; while (*chp != '\0') { nr_entries += 1; chp = skip_token (chp); } if ((nr_entries % modulo) != 0) { hw_abort (current, "incorrect number of entries for %s property %s, should be multiple of %d", property_name, property_value, modulo); } return nr_entries / modulo;}/* parse: <address> ::= <token> ; device dependant */static const char *parse_address (struct hw *current, struct hw *bus, const char *chp, hw_unit *address){ if (hw_unit_decode (bus, chp, address) < 0) hw_abort (current, "invalid unit address in %s", chp); return skip_token (chp);}/* parse: <size> ::= <number> { "," <number> } ; */static const char *parse_size (struct hw *current, struct hw *bus, const char *chp, hw_unit *size){ int i; int nr; const char *curr = chp; memset(size, 0, sizeof(*size)); /* parse the numeric list */ size->nr_cells = hw_unit_nr_size_cells (bus); nr = 0; while (1) { char *next; size->cells[nr] = strtoul (curr, &next, 0); if (curr == next) hw_abort (current, "Problem parsing <size> %s", chp); nr += 1; if (next[0] != ',') break; if (nr == size->nr_cells) hw_abort (current, "Too many values in <size> %s", chp); curr = next + 1; } ASSERT (nr > 0 && nr <= size->nr_cells); /* right align the numbers */ for (i = 1; i <= size->nr_cells; i++) { if (i <= nr) size->cells[size->nr_cells - i] = size->cells[nr - i]; else size->cells[size->nr_cells - i] = 0; } return skip_token (chp);}/* parse: <reg> ::= { <address> <size> } ; */static voidparse_reg_property (struct hw *current, const char *property_name, const char *property_value){ int nr_regs; int reg_nr; reg_property_spec *regs; const char *chp; /* determine the number of reg entries by counting tokens */ nr_regs = count_entries (current, property_name, property_value, 2); /* create working space */ regs = zalloc (nr_regs * sizeof (*regs)); /* fill it in */ chp = property_value; for (reg_nr = 0; reg_nr < nr_regs; reg_nr++) { chp = parse_address (current, hw_parent(current), chp, ®s[reg_nr].address); chp = parse_size (current, hw_parent(current), chp, ®s[reg_nr].size); } /* create it */ hw_add_reg_array_property (current, property_name, regs, nr_regs); zfree (regs);}/* { <child-address> <parent-address> <child-size> }* */static voidparse_ranges_property (struct hw *current, const char *property_name, const char *property_value){ int nr_ranges; int range_nr; range_property_spec *ranges; const char *chp; /* determine the number of ranges specified */ nr_ranges = count_entries (current, property_name, property_value, 3); /* create a property of that size */ ranges = zalloc (nr_ranges * sizeof(*ranges)); /* fill it in */ chp = property_value; for (range_nr = 0; range_nr < nr_ranges; range_nr++) { chp = parse_address (current, current, chp, &ranges[range_nr].child_address); chp = parse_address (current, hw_parent(current), chp, &ranges[range_nr].parent_address); chp = parse_size (current, current, chp, &ranges[range_nr].size); } /* create it */ hw_add_range_array_property (current, property_name, ranges, nr_ranges); zfree (ranges);}/* <integer> ... */static voidparse_integer_property (struct hw *current, const char *property_name, const char *property_value){ int nr_entries; unsigned_cell words[1024]; /* integer or integer array? */ nr_entries = 0; while (1) { char *end; words[nr_entries] = strtoul (property_value, &end, 0); if (property_value == end) break; nr_entries += 1; if (nr_entries * sizeof (words[0]) >= sizeof (words)) hw_abort (current, "buffer overflow"); property_value = end; } if (nr_entries == 0) hw_abort (current, "error parsing integer property %s (%s)", property_name, property_value); else if (nr_entries == 1) hw_add_integer_property (current, property_name, words[0]); else { int i; for (i = 0; i < nr_entries; i++) { H2BE (words[i]); } /* perhaps integer array property is better */ hw_add_array_property (current, property_name, words, sizeof(words[0]) * nr_entries); }}/* <string> ... */static voidparse_string_property (struct hw *current, const char *property_name, const char *property_value){ char **strings; const char *chp; int nr_strings; int approx_nr_strings; /* get an estimate as to the number of strings by counting double quotes */ approx_nr_strings = 2; for (chp = property_value; *chp; chp++) { if (*chp == '"') approx_nr_strings++; } approx_nr_strings = (approx_nr_strings) / 2; /* create a string buffer for that many (plus a null) */ strings = (char**) zalloc ((approx_nr_strings + 1) * sizeof(char*)); /* now find all the strings */ chp = property_value; nr_strings = 0; while (1) { /* skip leading space */ while (*chp != '\0' && isspace (*chp)) chp += 1; if (*chp == '\0') break; /* copy it in */ if (*chp == '"') { /* a quoted string - watch for '\' et al. */ /* estimate the size and allocate space for it */ int pos; chp++; pos = 0; while (chp[pos] != '\0' && chp[pos] != '"') { if (chp[pos] == '\\' && chp[pos+1] != '\0') pos += 2; else pos += 1; } strings[nr_strings] = zalloc (pos + 1); /* copy the string over */ pos = 0; while (*chp != '\0' && *chp != '"') { if (*chp == '\\' && *(chp+1) != '\0') { strings[nr_strings][pos] = *(chp+1); chp += 2; pos++; } else { strings[nr_strings][pos] = *chp; chp += 1; pos++; } } if (*chp != '\0') chp++; strings[nr_strings][pos] = '\0'; } else { /* copy over a single unquoted token */ int len = 0; while (chp[len] != '\0' && !isspace(chp[len])) len++; strings[nr_strings] = zalloc(len + 1); strncpy(strings[nr_strings], chp, len); strings[nr_strings][len] = '\0'; chp += len; } nr_strings++; if (nr_strings > approx_nr_strings) hw_abort (current, "String property %s badly formatted", property_name); } ASSERT (strings[nr_strings] == NULL); /* from zalloc */ /* install it */ if (nr_strings == 0) hw_add_string_property (current, property_name, ""); else if (nr_strings == 1) hw_add_string_property (current, property_name, strings[0]); else { const char **specs = (const char**) strings; /* stop a bogus error */ hw_add_string_array_property (current, property_name, specs, nr_strings); } /* flush the created string */ while (nr_strings > 0) { nr_strings--; zfree (strings[nr_strings]); } zfree(strings);}/* <path-to-ihandle-device> */#if NOT_YETstatic voidparse_ihandle_property (struct hw *current, const char *property, const char *value){ ihandle_runtime_property_spec ihandle; /* pass the full path */ ihandle.full_path = value; /* save this ready for the ihandle create */ hw_add_ihandle_runtime_property (current, property, &ihandle);}#endifstruct hw *hw_tree_create (SIM_DESC sd, const char *family){ return hw_create (sd, NULL, family, family, NULL, NULL);}voidhw_tree_delete (struct hw *me){ /* Need to allow devices to disapear under our feet */ while (hw_child (me) != NULL) { hw_tree_delete (hw_child (me)); } hw_delete (me);}struct hw *hw_tree_parse (struct hw *current, const char *fmt, ...){ va_list ap; va_start (ap, fmt); current = hw_tree_vparse (current, fmt, ap); va_end (ap); return current;} struct hw *hw_tree_vparse (struct hw *current, const char *fmt, va_list ap){ char device_specifier[1024]; name_specifier spec; /* format the path */ vsprintf (device_specifier, fmt, ap); if (strlen (device_specifier) >= sizeof (device_specifier)) hw_abort (NULL, "device_tree_add_deviced: buffer overflow\n"); /* construct the tree down to the final struct hw */ current = split_fill_path (current, device_specifier, &spec); /* is there an interrupt spec */ if (spec.property == NULL && spec.value != NULL) { char *op = split_value (&spec); switch (op[0]) { case '>': { char *my_port_name = split_value (&spec); int my_port; char *dest_port_name = split_value (&spec); int dest_port; name_specifier dest_spec; char *dest_hw_name = split_value (&spec); struct hw *dest; /* find my name */ if (!hw_finished_p (current)) hw_finish (current); my_port = hw_port_decode (current, my_port_name, output_port); /* find the dest device and port */ dest = split_fill_path (current, dest_hw_name, &dest_spec); if (!hw_finished_p (dest)) hw_finish (dest); dest_port = hw_port_decode (dest, dest_port_name, input_port); /* connect the two */ hw_port_attach (current, my_port, dest, dest_port, permenant_object); break; } default: hw_abort (current, "unreconised interrupt spec %s\n", spec.value); break; } } /* is there a property */ if (spec.property != NULL) { if (strcmp (spec.value, "true") == 0) hw_add_boolean_property (current, spec.property, 1); else if (strcmp (spec.value, "false") == 0) hw_add_boolean_property (current, spec.property, 0); else { const struct hw_property *property; switch (spec.value[0]) {#if NOT_YET case '*': { parse_ihandle_property (current, spec.property, spec.value + 1); break; }#endif case '[': { unsigned8 words[1024]; char *curr = spec.value + 1; int nr_words = 0; while (1) { char *next; words[nr_words] = H2BE_1 (strtoul (curr, &next, 0)); if (curr == next) break; curr = next; nr_words += 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -