📄 tree.c
字号:
(const char *)skip_token(const char *chp){ while (!isspace(*chp) && *chp != '\0') chp++; while (isspace(*chp) && *chp != '\0') chp++; return chp;}/* count the number of entries */STATIC_INLINE_TREE\(int)count_entries(device *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) { device_error(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_INLINE_TREE\(const char *)parse_address(device *current, device *bus, const char *chp, device_unit *address){ ASSERT(device_nr_address_cells(bus) > 0); if (device_decode_unit(bus, chp, address) < 0) device_error(current, "invalid unit address in %s", chp); return skip_token(chp);}/* parse: <size> ::= <number> { "," <number> } ; */STATIC_INLINE_TREE\(const char *)parse_size(device *current, device *bus, const char *chp, device_unit *size){ int i; int nr; const char *curr = chp; memset(size, 0, sizeof(*size)); /* parse the numeric list */ size->nr_cells = device_nr_size_cells(bus); nr = 0; ASSERT(size->nr_cells > 0); while (1) { char *next; size->cells[nr] = strtoul(curr, &next, 0); if (curr == next) device_error(current, "Problem parsing <size> %s", chp); nr += 1; if (next[0] != ',') break; if (nr == size->nr_cells) device_error(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_INLINE_TREE\(void)parse_reg_property(device *current, const char *property_name, const char *property_value){ int nr_regs; int reg_nr; reg_property_spec *regs; const char *chp; device *bus = device_parent(current); /* determine the number of reg entries by counting tokens */ nr_regs = count_entries(current, property_name, property_value, 1 + (device_nr_size_cells(bus) > 0)); /* 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, bus, chp, ®s[reg_nr].address); if (device_nr_size_cells(bus) > 0) chp = parse_size(current, bus, chp, ®s[reg_nr].size); else memset(®s[reg_nr].size, sizeof (®s[reg_nr].size), 0); } /* create it */ device_add_reg_array_property(current, property_name, regs, nr_regs); zfree(regs);}/* { <child-address> <parent-address> <child-size> }* */STATIC_INLINE_TREE\(void)parse_ranges_property(device *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, device_parent(current), chp, &ranges[range_nr].parent_address); chp = parse_size(current, current, chp, &ranges[range_nr].size); } /* create it */ device_add_range_array_property(current, property_name, ranges, nr_ranges); zfree(ranges);}/* <integer> ... */STATIC_INLINE_TREE\(void)parse_integer_property(device *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)) device_error(current, "buffer overflow"); property_value = end; } if (nr_entries == 0) device_error(current, "error parsing integer property %s (%s)", property_name, property_value); else if (nr_entries == 1) device_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 */ device_add_array_property(current, property_name, words, sizeof(words[0]) * nr_entries); }}/* <string> ... */STATIC_INLINE_TREE\(void)parse_string_property(device *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) device_error(current, "String property %s badly formatted", property_name); } ASSERT(strings[nr_strings] == NULL); /* from zalloc */ /* install it */ if (nr_strings == 0) device_add_string_property(current, property_name, ""); else if (nr_strings == 1) device_add_string_property(current, property_name, strings[0]); else { const char **specs = (const char**)strings; /* stop a bogus error */ device_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> */STATIC_INLINE_TREE\(void)parse_ihandle_property(device *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 */ device_add_ihandle_runtime_property(current, property, &ihandle);}EXTERN_TREE\(device *)tree_parse(device *current, const char *fmt, ...){ char device_specifier[1024]; name_specifier spec; /* format the path */ { va_list ap; va_start(ap, fmt); vsprintf(device_specifier, fmt, ap); va_end(ap); if (strlen(device_specifier) >= sizeof(device_specifier)) error("device_tree_add_deviced: buffer overflow\n"); } /* construct the tree down to the final device */ 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_device_name = split_value(&spec); device *dest; /* find my name */ my_port = device_interrupt_decode(current, my_port_name, output_port); /* find the dest device and port */ dest = split_fill_path(current, dest_device_name, &dest_spec); dest_port = device_interrupt_decode(dest, dest_port_name, input_port); /* connect the two */ device_interrupt_attach(current, my_port, dest, dest_port, permenant_object); } break; default: device_error(current, "unreconised interrupt spec %s\n", spec.value); break; } } /* is there a property */ if (spec.property != NULL) { if (strcmp(spec.value, "true") == 0) device_add_boolean_property(current, spec.property, 1); else if (strcmp(spec.value, "false") == 0) device_add_boolean_property(current, spec.property, 0); else { const device_property *property; switch (spec.value[0]) { case '*': parse_ihandle_property(current, spec.property, spec.value + 1); break; 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; } device_add_array_property(current, spec.property, words, sizeof(words[0]) * nr_words); } break; case '"': parse_string_property(current, spec.property, spec.value); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -