static unsigned int attr_lookup_as_uint(const char** attr, const char* name) { const char* valuestr = attr_lookup(attr, name); if (valuestr == NULL) return 0; unsigned int value = strtoul(valuestr, NULL, 0); return value; }
static char *get_token(struct element_group *g, struct element *e, const char *token, char *buf, size_t len) { if (!strncasecmp(token, "group:", 6)) { const char *n = token + 6; if (!strcasecmp(n, "nelements")) { snprintf(buf, len, "%u", g->g_nelements); return buf; } else if (!strcasecmp(n, "name")) return g->g_name; else if (!strcasecmp(n, "title")) return g->g_hdr->gh_title; } else if (!strncasecmp(token, "element:", 8)) { const char *n = token + 8; if (!strcasecmp(n, "name")) return e->e_name; else if (!strcasecmp(n, "description")) return e->e_description; else if (!strcasecmp(n, "nattrs")) { snprintf(buf, len, "%u", e->e_nattrs); return buf; } else if (!strcasecmp(n, "lifecycles")) { snprintf(buf, len, "%u", e->e_lifecycles); return buf; } else if (!strcasecmp(n, "level")) { snprintf(buf, len, "%u", e->e_level); return buf; } else if (!strcasecmp(n, "parent")) return e->e_parent ? e->e_parent->e_name : ""; else if (!strcasecmp(n, "id")) { snprintf(buf, len, "%u", e->e_id); return buf; } else if (!strcasecmp(n, "rxusage")) { snprintf(buf, len, "%2.0f", e->e_rx_usage == FLT_MAX ? e->e_rx_usage : 0.0f); return buf; } else if (!strcasecmp(n, "txusage")) { snprintf(buf, len, "%2.0f", e->e_tx_usage == FLT_MAX ? e->e_tx_usage : 0.0f); return buf; } else if (!strcasecmp(n, "haschilds")) { snprintf(buf, len, "%u", list_empty(&e->e_childs) ? 0 : 1); return buf; } } else if (!strncasecmp(token, "attr:", 5)) { const char *type = token + 5; char *name = strchr(type, ':'); struct attr_def *def; struct attr *a; if (!name) { fprintf(stderr, "Invalid attribute field \"%s\"\n", type); goto out; } name++; def = attr_def_lookup(name); if (!def) { fprintf(stderr, "Undefined attribute \"%s\"\n", name); goto out; } if (!(a = attr_lookup(e, def->ad_id))) { fprintf(stderr, "Unable to find attribute %u (%s)\n", def->ad_id, name); goto out; } if (!strncasecmp(type, "rx:", 3)) { snprintf(buf, len, "%lu", a->a_rx_rate.r_total); return buf; } else if (!strncasecmp(type, "tx:", 3)) { snprintf(buf, len, "%lu", a->a_tx_rate.r_total); return buf; } else if (!strncasecmp(type, "rxrate:", 7)) { snprintf(buf, len, "%.2f", a->a_rx_rate.r_rate); return buf; } else if (!strncasecmp(token+5, "txrate:", 7)) snprintf(buf, len, "%.2f", a->a_tx_rate.r_rate); return buf; } fprintf(stderr, "Unknown field \"%s\"\n", token); out: return "unknown"; }
static void XMLCALL on_element_start(void* data, const XML_Char* element, const XML_Char** attr) { HangulKeyboardLoadContext* context = (HangulKeyboardLoadContext*)data; if (strcmp(element, "hangul-keyboard") == 0) { if (context->keyboard != NULL) { hangul_keyboard_delete(context->keyboard); } context->keyboard = hangul_keyboard_new(); const char* id = attr_lookup(attr, "id"); hangul_keyboard_set_id(context->keyboard, id); const char* typestr = attr_lookup(attr, "type"); int type = HANGUL_KEYBOARD_TYPE_JAMO; if (strcmp(typestr, "jamo") == 0) { type = HANGUL_KEYBOARD_TYPE_JAMO; } else if (strcmp(typestr, "jamo-yet") == 0) { type = HANGUL_KEYBOARD_TYPE_JAMO_YET; } else if (strcmp(typestr, "jaso") == 0) { type = HANGUL_KEYBOARD_TYPE_JASO; } else if (strcmp(typestr, "jaso-yet") == 0) { type = HANGUL_KEYBOARD_TYPE_JASO_YET; } else if (strcmp(typestr, "romaja") == 0) { type = HANGUL_KEYBOARD_TYPE_ROMAJA; } hangul_keyboard_set_type(context->keyboard, type); } else if (strcmp(element, "name") == 0) { if (context->keyboard == NULL) return; const char* lang = attr_lookup(attr, "xml:lang"); if (lang == NULL) { context->save_name = true; } else { const char* locale = setlocale(LC_ALL, NULL); size_t n = strlen(lang); if (strncmp(lang, locale, n) == 0) { context->save_name = true; } } context->current_element = "name"; } else if (strcmp(element, "map") == 0) { if (context->keyboard == NULL) return; unsigned int id = attr_lookup_as_uint(attr, "id"); if (id < countof(context->keyboard->table)) { context->current_id = id; context->current_element = "map"; } } else if (strcmp(element, "combination") == 0) { if (context->keyboard == NULL) return; unsigned int id = attr_lookup_as_uint(attr, "id"); if (id < countof(context->keyboard->combination)) { if (context->keyboard->combination[id] != NULL) { hangul_combination_delete(context->keyboard->combination[id]); } context->current_id = id; context->current_element = "combination"; context->keyboard->combination[id] = hangul_combination_new(); } } else if (strcmp(element, "item") == 0) { if (context->keyboard == NULL) return; unsigned int id = context->current_id; if (strcmp(context->current_element, "map") == 0) { HangulKeyboard* keyboard = context->keyboard; unsigned int key = attr_lookup_as_uint(attr, "key"); unsigned int value = attr_lookup_as_uint(attr, "value"); hangul_keyboard_set_mapping(keyboard, id, key, value); } else if (strcmp(context->current_element, "combination") == 0) { HangulCombination* combination = context->keyboard->combination[id]; unsigned int first = attr_lookup_as_uint(attr, "first"); unsigned int second = attr_lookup_as_uint(attr, "second"); unsigned int result = attr_lookup_as_uint(attr, "result"); hangul_combination_add_item(combination, first, second, result); } } else if (strcmp(element, "include") == 0) { const char* file = attr_lookup(attr, "file"); if (file == NULL) return; size_t n = strlen(file) + strlen(context->path) + 1; char* path = malloc(n); if (path == NULL) return; if (file[0] == '/') { strncpy(path, file, n); } else { char* orig_path = strdup(context->path); char* dir = dirname(orig_path); snprintf(path, n, "%s/%s", dir, file); free(orig_path); } hangul_keyboard_parse_file(path, context); free(path); } }
/* * Identify the attribute in <attr_name>. * * Check if * 1) the attribute has been defined already * 2) the value count is correct * 3) the assign op is appropriate * * Invoke appropriate parser. * * This function will return FAILED only if its in the default section * and an attribute cannot be ID'd. Otherwise, it returns OK. */ static status_e identify_attribute( entry_e entry_type, struct service_config *scp, const char *attr_name, enum assign_op op, pset_h attr_values ) { const struct attribute *ap ; const char *func = "identify_attribute" ; if ( entry_type == SERVICE_ENTRY ) ap = attr_lookup( service_attributes, attr_name ) ; else ap = attr_lookup( default_attributes, attr_name ) ; if ( ap == NULL ) return OK; /* We simply ignore keywords not on the list */ if ( ! MODIFIABLE( ap ) ) { if ( SC_SPECIFIED( scp, ap->a_id ) ) { parsemsg( LOG_WARNING, func, "Service %s: attribute already set: %s", SC_NAME(scp), attr_name ) ; return OK; } if ( op != SET_EQ ) { parsemsg( LOG_WARNING, func, "Service %s: operator '%s' cannot be used for attribute '%s'", SC_NAME(scp), ( op == PLUS_EQ ) ? "+=" : "-=", attr_name ) ; return OK; } } else /* modifiable attribute */ { /* * For the defaults entry, '=' and '+=' have the same meaning */ if ( entry_type == DEFAULTS_ENTRY && op == SET_EQ ) op = PLUS_EQ ; } if ( FIXED_VALUES( ap ) && (unsigned)ap->a_nvalues != pset_count( attr_values ) ) { parsemsg( LOG_WARNING, func, "attribute %s expects %d values and %d values were specified", attr_name, ap->a_nvalues, pset_count( attr_values ) ) ; return OK; } if ( (*ap->a_parser)( attr_values, scp, op ) == OK ) { /* This is the normal path. */ SC_SPECIFY( scp, ap->a_id ) ; } else if ( entry_type == SERVICE_ENTRY ) { parsemsg( LOG_ERR, func, "Error parsing attribute %s - DISABLING SERVICE", attr_name ) ; SC_DISABLE( scp ); } /* * We are in the default section and an error was detected. At * this point, we should terminate since whatever attribute * was trying to be specified cannot be propagated. */ else if ( !debug.on ) return FAILED; return OK; }