NEOERR *wdb_create (WDB **wdb, const char *path, const char *name, const char *key, ULIST *col_def, int flags) { WDB *my_wdb; char d_path[_POSIX_PATH_MAX]; NEOERR *err = STATUS_OK; int x, len, r; char *s; *wdb = NULL; err = wdb_alloc (&my_wdb, flags); if (err) return nerr_pass(err); my_wdb->name = strdup (name); my_wdb->key = strdup (key); my_wdb->path = strdup(path); if (my_wdb->name == NULL || my_wdb->key == NULL || my_wdb->path == NULL) { wdb_destroy (&my_wdb); return nerr_raise (NERR_NOMEM, "Unable to allocate memory for creation of %s", name); } /* ondisk must start at one because of skipList */ my_wdb->last_ondisk = 1; len = uListLength(col_def); for (x = 0; x < len; x++) { err = uListGet (col_def, x, (void *)&s); if (err) { wdb_destroy (&my_wdb); return nerr_pass(err); } err = wdb_column_insert (my_wdb, -1, s, WDB_TYPE_STR); my_wdb->defn_dirty = 0; /* So we don't save on error destroy */ if (err) { wdb_destroy (&my_wdb); return nerr_pass(err); } } err = wdb_save_defn (my_wdb, path); if (err) { wdb_destroy (&my_wdb); return nerr_pass(err); } snprintf (d_path, sizeof(d_path), "%s.wdb", path); r = db_open(d_path, DB_BTREE, DB_CREATE | DB_TRUNCATE, 0, NULL, NULL, &(my_wdb->db)); if (r) { wdb_destroy (&my_wdb); return nerr_raise (NERR_DB, "Unable to create db file %s: %d", d_path, r); } *wdb = my_wdb; return STATUS_OK; }
NEOERR *wdbr_next (WDB *wdb, WDBCursor *cursor, WDBRow **row, int flags) { DBT dkey, data; WDBRow *my_row; NEOERR *err = STATUS_OK; int r; *row = NULL; if (wdb->table_version != cursor->table_version) { return nerr_raise (NERR_ASSERT, "Cursor doesn't match database"); } memset(&dkey, 0, sizeof(dkey)); memset(&data, 0, sizeof(data)); dkey.flags = DB_DBT_MALLOC; data.flags = DB_DBT_MALLOC; /* First call */ if (flags & WDBC_FIRST) { r = cursor->db_cursor->c_get (cursor->db_cursor, &dkey, &data, DB_FIRST); if (r == DB_NOTFOUND) return nerr_raise (NERR_NOT_FOUND, "Cursor empty"); else if (r) return nerr_raise (NERR_DB, "Unable to get first item from cursor: %d", r); } else { r = cursor->db_cursor->c_get (cursor->db_cursor, &dkey, &data, DB_NEXT); if (r == DB_NOTFOUND) return STATUS_OK; else if (r) return nerr_raise (NERR_DB, "Unable to get next item from cursor: %d", r); } /* allocate row */ err = alloc_row (wdb, &my_row); if (err) { free (data.data); return nerr_pass(err); } my_row->key_value = (char *) malloc (dkey.size + 1); if (my_row->key_value == NULL) { free (data.data); free (my_row); return nerr_raise (NERR_NOMEM, "No memory for new row"); } memcpy (my_row->key_value, dkey.data, dkey.size); my_row->key_value[dkey.size] = '\0'; /* unpack row */ err = unpack_row (wdb, data.data, data.size, my_row); free (data.data); free (dkey.data); if (err) { free (my_row); return nerr_pass(err); } *row = my_row; return STATUS_OK; }
/* * application logic message, called by msparse_buf() */ static NEOERR* msparse_msg(moc_srv *srv, unsigned char *buf, size_t len, moc_arg *arg) { uint32_t id, reply; unsigned char *payload; size_t psize, rv; MOC_NOT_NULLB(arg, arg->evth); if (!srv || !buf || len < 8) return nerr_raise(NERR_ASSERT, "illegal packet"); //MSG_DUMP("recv: ", buf, len); /* The header is: * 4 bytes ID * 4 bytes Reply Code * Variable Payload */ id = ntohl(* ((uint32_t *) buf)); reply = ntohl(* ((uint32_t *) buf + 1)); payload = buf + 8; psize = len - 8; if (id == 0 && reply == 10000) { /* * server push */ if (psize < 4) return nerr_raise(NERR_ASSERT, "server pushed empty message"); struct msqueue_entry *e = msqueue_entry_create(); if (!e) return nerr_raise(NERR_NOMEM, "alloc msqueue entry"); rv = unpack_hdf(payload + 4, psize - 4, &(e->hdfrcv)); if (rv <= 0) return nerr_raise(NERR_ASSERT, "server pushed illegal message"); //TRACE_HDF(e->hdfrcv); char *cmd = NULL; HDF_ATTR *attr = hdf_get_attr(e->hdfrcv, "_Reserve"); while (attr != NULL) { if (!strcmp(attr->key, "cmd")) cmd = attr->value; attr = attr->next; } if (!cmd) return nerr_raise(NERR_ASSERT, "cmd not supplied"); e->ename = strdup(srv->evt->ename); e->cmd = strdup(cmd); mtc_dbg("receive cmd %s", cmd); hdf_remove_tree(e->hdfrcv, "_Reserve"); mssync_lock(&arg->callbacksync); msqueue_put(arg->callbackqueue, e); mssync_unlock(&arg->callbacksync); /* * notify callback thread */ mssync_signal(&arg->callbacksync); } else { /* * server response */ if (id < g_reqid) return nerr_raise(NERR_ASSERT, "id not match %d %d", g_reqid, id); if (psize >= 4) { mssync_lock(&(arg->mainsync)); rv = unpack_hdf(payload + 4, psize - 4, &(srv->evt->hdfrcv)); mssync_unlock(&(arg->mainsync)); if (rv <= 0) return nerr_raise(NERR_ASSERT, "server responsed illegal message"); //TRACE_HDF(srv->evt->hdfrcv); } /* * notify main thread */ mssync_signal(&(arg->mainsync)); } return STATUS_OK; }
NEOERR* oms_users_data_add(CGI *cgi, HASH *dbh, HASH *evth, session_t *ses) { mevent_t *evt = (mevent_t*)hash_lookup(evth, "aic"); char *aname, *pname, *email; int cost; NEOERR *err; APP_CHECK_ADMIN(); HDF_GET_STR_IDENT(cgi->hdf, PRE_COOKIE".aname", pname); HDF_GET_STR(cgi->hdf, PRE_QUERY".aname", aname); HDF_GET_STR(cgi->hdf, PRE_QUERY".email", email); LEGAL_CK_ANAME(pname); LEGAL_CK_ANAME(aname); LEGAL_CK_EMAIL(email); /* * check */ int state = hdf_get_int_value(evt->hdfrcv, "state", LCS_ST_FREE); if (state <= LCS_ST_FREE) return nerr_raise(LERR_NEEDUP, "%s want to add users %s", pname, aname); else if (state >= LCS_ST_VIP) goto add; /* * chargeback */ cost = hdf_get_int_value(g_cfg, "Cost.account", 0); evt = (mevent_t*)hash_lookup(evth, "bank"); hdf_set_value(evt->hdfsnd, "aname", pname); hdf_set_int_value(evt->hdfsnd, "btype", BANK_OP_ADDACCOUNT); hdf_set_int_value(evt->hdfsnd, "fee", cost); hdf_set_value(evt->hdfsnd, "account", aname); MEVENT_TRIGGER(evt, pname, REQ_CMD_BANK_ADDBILL, FLAGS_SYNC); add: /* * add */ evt = (mevent_t*)hash_lookup(evth, "aic"); hdf_copy(evt->hdfsnd, NULL, hdf_get_obj(cgi->hdf, PRE_QUERY)); hdf_set_value(evt->hdfsnd, "pname", pname); hdf_set_value(evt->hdfsnd, "aname", aname); hdf_set_int_value(evt->hdfsnd, "state", hdf_get_int_value(evt->hdfrcv, "state", LCS_ST_FREE)); hdf_set_value(evt->hdfsnd, "masn", aname); if (PROCESS_NOK(mevent_trigger(evt, aname, REQ_CMD_APPNEW, FLAGS_SYNC))) { char *zpa = NULL; hdf_write_string(evt->hdfrcv, &zpa); mtc_foo("add %s failure %d %s", aname, evt->errcode, zpa); SAFE_FREE(zpa); if (state < LCS_ST_VIP) { /* * roll back */ evt = (mevent_t*)hash_lookup(evth, "bank"); hdf_set_value(evt->hdfsnd, "aname", pname); hdf_set_int_value(evt->hdfsnd, "btype", BANK_OP_ROLLBACK); hdf_set_int_value(evt->hdfsnd, "fee", -cost); hdf_set_valuef(evt->hdfsnd, "remark = 客服帐号 %s 创建失败", aname); if (PROCESS_NOK(mevent_trigger(evt, pname, REQ_CMD_BANK_ADDBILL, FLAGS_SYNC))) { /* * ATTENTION we need pay back to customer manually */ hdf_write_string(evt->hdfrcv, &zpa); mtc_foo("rollback %s failure %d %s", aname, evt->errcode, zpa); SAFE_FREE(zpa); } } return nerr_raise(evt->errcode, "add %s failure %d", aname, evt->errcode); } return STATUS_OK; }
NEOERR* mast_dds_load(char *dir, char *name, RendAsset **a) { char fname[PATH_MAX], *buf, *pos; NEOERR *err; DdsLoadInfo loadInfoDXT1 = { 1, 0, 0, 4, 8, GL_COMPRESSED_RGBA_S3TC_DXT1 }; DdsLoadInfo loadInfoDXT3 = { 1, 0, 0, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT3 }; DdsLoadInfo loadInfoDXT5 = { 1, 0, 0, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT5 }; DdsLoadInfo loadInfoBGRA8 = { 0, 0, 0, 1, 4, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE }; DdsLoadInfo loadInfoBGR8 = { 0, 0, 0, 1, 3, GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE }; DdsLoadInfo loadInfoBGR5A1 = { 0, 1, 0, 1, 2, GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV }; DdsLoadInfo loadInfoBGR565 = { 0, 1, 0, 1, 2, GL_RGB5, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }; DdsLoadInfo loadInfoIndex8 = { 0, 0, 1, 1, 1, GL_RGB8, GL_BGRA, GL_UNSIGNED_BYTE }; if (dir) snprintf(fname, sizeof(fname), "%s%s", dir, name); else strncpy(fname, name, sizeof(fname)); TexAsset *tnode = mtex_node_new(); if (!tnode) return nerr_raise(NERR_NOMEM, "alloc texture"); DDS_header hdr; int x = 0; int y = 0; int mipMapCount = 0; int totallen = 0; err = ne_load_file_len(fname, &buf, &totallen); if (err != STATUS_OK) return nerr_pass(err); glEnable(GL_TEXTURE_2D); glGenTextures(1, &tnode->tex); glBindTexture(GL_TEXTURE_2D, tnode->tex); pos = buf; memcpy(&hdr, buf, sizeof(hdr)); pos += sizeof(hdr); if (pos - buf > totallen) return nerr_raise(NERR_ASSERT, "file too short"); if (hdr.dwMagic != DDS_MAGIC || hdr.dwSize != 124 || !(hdr.dwFlags & DDSD_PIXELFORMAT) || !(hdr.dwFlags & DDSD_CAPS) ) return nerr_raise(NERR_ASSERT, "%s Does not appear to be a .dds file", fname); x = hdr.dwWidth; y = hdr.dwHeight; if (!is_power_of_two(x)) { mtc_warn("Texture %s with is %i pixels which is not a power of two!", fname, x); } if (!is_power_of_two(y)) { mtc_warn("Texture %s height is %i pixels which is not a power of two!", fname, y); } DdsLoadInfo* li = &loadInfoDXT1; if (PF_IS_DXT1(hdr.sPixelFormat)) { li = &loadInfoDXT1; } else if (PF_IS_DXT3(hdr.sPixelFormat)) { li = &loadInfoDXT3; } else if (PF_IS_DXT5(hdr.sPixelFormat)) { li = &loadInfoDXT5; } else if (PF_IS_BGRA8(hdr.sPixelFormat)) { li = &loadInfoBGRA8; } else if (PF_IS_BGR8(hdr.sPixelFormat)) { li = &loadInfoBGR8; } else if (PF_IS_BGR5A1(hdr.sPixelFormat)) { li = &loadInfoBGR5A1; } else if (PF_IS_BGR565(hdr.sPixelFormat)) { li = &loadInfoBGR565; } else if (PF_IS_INDEX8(hdr.sPixelFormat)) { li = &loadInfoIndex8; } else { return nerr_raise(NERR_ASSERT, "%s: Unknown DDS File format type.", fname); } glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); mipMapCount = (hdr.dwFlags & DDSD_MIPMAPCOUNT) ? hdr.dwMipMapCount : 1; int ix, zz; GLenum cFormat, format; if (li->compressed) { size_t size = max(li->divSize, x) / li->divSize * max(li->divSize, y) / li->divSize * li->blockBytes; char *data = malloc(size); if (!data ) { return nerr_raise(NERR_ASSERT, "%s: not contain any data.", fname); } cFormat = li->internalFormat; format = li->internalFormat; for( ix = 0; ix < mipMapCount; ++ix ) { memcpy(data, pos, size); pos += size; if (pos - buf > totallen) return nerr_raise(NERR_ASSERT, "file too short"); glCompressedTexImage2D(GL_TEXTURE_2D, ix, li->internalFormat, x, y, 0, size, data); x = (x+1)>>1; y = (y+1)>>1; size = max(li->divSize, x) / li->divSize * max(li->divSize, y) / li->divSize * li->blockBytes; } free(data); } else if (li->palette) {
/* Client side */ NEOERR *ne_net_connect(NSOCK **sock, const char *host, int port, int conn_timeout, int data_timeout) { struct sockaddr_in serv_addr; struct hostent hp; struct hostent *php; int fd; int r = 0, x; int flags; struct timeval tv; fd_set fds; int optval; socklen_t optlen; NSOCK *my_sock; /* FIXME: This isn't thread safe... but there's no man entry for the _r * version? */ php = gethostbyname(host); if (php == NULL) { return nerr_raise(NERR_IO, "Host not found: %s", hstrerror(h_errno)); } hp = *php; memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(port); fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd == -1) return nerr_raise_errno(NERR_IO, "Unable to create socket"); flags = fcntl(fd, F_GETFL, 0 ); if (flags == -1) { close(fd); return nerr_raise_errno(NERR_IO, "Unable to get socket flags"); } if (fcntl(fd, F_SETFL, flags | O_NDELAY) == -1) { close(fd); return nerr_raise_errno(NERR_IO, "Unable to set O_NDELAY"); } x = 0; while (hp.h_addr_list[x] != NULL) { memcpy(&(serv_addr.sin_addr), hp.h_addr_list[x], sizeof(struct in_addr)); errno = 0; r = connect(fd, (struct sockaddr *) &(serv_addr), sizeof(struct sockaddr_in)); if (r == 0 || errno == EINPROGRESS) break; x++; } if (r != 0) { if (errno != EINPROGRESS) { close(fd); return nerr_raise_errno(NERR_IO, "Unable to connect to %s:%d", host, port); } tv.tv_sec = conn_timeout; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(fd, &fds); r = select(fd+1, NULL, &fds, NULL, &tv); if (r == 0) { close(fd); return nerr_raise(NERR_IO, "Connection to %s:%d failed: Timeout", host, port); } if (r < 0) { close(fd); return nerr_raise_errno(NERR_IO, "Connection to %s:%d failed", host, port); } optlen = sizeof(optval); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) { close(fd); return nerr_raise_errno(NERR_IO, "Unable to getsockopt to determine connection error"); } if (optval) { close(fd); errno = optval; return nerr_raise_errno(NERR_IO, "Connection to %s:%d failed", host, port); } } /* Re-enable blocking... we'll use select on read/write for timeouts * anyways, and if we want non-blocking version in the future we'll * add a flag or something. */ flags = fcntl(fd, F_GETFL, 0 ); if (flags == -1) { close(fd); return nerr_raise_errno(NERR_IO, "Unable to get socket flags"); } if (fcntl(fd, F_SETFL, flags & ~O_NDELAY) == -1) { close(fd); return nerr_raise_errno(NERR_IO, "Unable to set O_NDELAY"); } my_sock = (NSOCK *) calloc(1, sizeof(NSOCK)); if (my_sock == NULL) { close(fd); return nerr_raise(NERR_NOMEM, "Unable to allocate memory for NSOCK"); } my_sock->fd = fd; my_sock->remote_ip = ntohl(serv_addr.sin_addr.s_addr); my_sock->remote_port = port; my_sock->data_timeout = data_timeout; my_sock->conn_timeout = conn_timeout; *sock = my_sock; return STATUS_OK; }
NEOERR* session_init(CGI *cgi, HASH *dbh, session_t **ses) { session_t *lses; HDF *node, *onode; char tok[LEN_HDF_KEY], *s; /* * follow cgi_parse(), to process _type_object */ s = hdf_get_value(cgi->hdf, PRE_QUERY"._type_object", NULL); if (s) { ULIST *list; string_array_split(&list, s, ",", 50); ITERATE_MLIST(list) { snprintf(tok, sizeof(tok), "%s.%s", PRE_QUERY, neos_strip((char*)list->items[t_rsv_i])); onode = hdf_get_obj(cgi->hdf, tok); if (onode) { mjson_export_to_hdf(onode, NULL, MJSON_EXPORT_NONE, false); } } uListDestroy(&list, ULIST_FREE); } *ses = NULL; lses = calloc(1, sizeof(session_t)); if (!lses) return nerr_raise(NERR_NOMEM, "calloc memory for session_t failure"); /* * mname */ HDF_FETCH_STR(cgi->hdf, PRE_COOKIE".mname", s); if (!s) HDF_FETCH_STR(cgi->hdf, PRE_COOKIE".username", s); if (s) lses->mname = strdup(s); /* * province */ HDF_FETCH_STR(cgi->hdf, PRE_COOKIE".province", s); hdf_init(&lses->province); if (s) { neos_unescape((UINT8*)s, strlen(s), '%'); hdf_set_value(lses->province, NULL, s); mjson_export_to_hdf(lses->province, MJSON_EXPORT_NONE, NULL, false); } /* * city */ HDF_FETCH_STR(cgi->hdf, PRE_COOKIE".city", s); hdf_init(&lses->city); if (s) { neos_unescape((UINT8*)s, strlen(s), '%'); hdf_set_value(lses->city, NULL, s); mjson_export_to_hdf(lses->city, MJSON_EXPORT_NONE, NULL, false); } /* * browser */ HDF_FETCH_STR(cgi->hdf, PRE_HTTP".UserAgent", s); if (s) { mstr_repchr(s, ' ', '\0'); for (int i = 0; i < m_browsers_size; i++) { if (!strncasecmp(s, m_browsers[i], strlen(m_browsers[i]))) { lses->browser = i; break; } } s = strchr(s, '/'); if (s) lses->bversion = strtof(s+1, NULL); } /* * reqtype */ lses->reqtype = CGI_REQ_HTML; char *uri = hdf_get_value(cgi->hdf, PRE_REQ_URI_RW, NULL); if (!uri) { uri = "terminal"; lses->reqtype = CGI_REQ_TERMINAL; } mstr_repchr(uri, '/', '_'); uri = mstr_strip(uri, '_'); if (!strncmp(uri, "json_", 5)) { uri = uri+5; lses->reqtype = CGI_REQ_AJAX; } else if (!strncmp(uri, "image_", 6)) { uri = uri+6; lses->reqtype = CGI_REQ_IMAGE; } /* * dataer, render */ switch (http_req_method(cgi)) { case CGI_REQ_POST: snprintf(tok, sizeof(tok), "%s_data_mod", uri); break; case CGI_REQ_PUT: snprintf(tok, sizeof(tok), "%s_data_add", uri); break; case CGI_REQ_DEL: snprintf(tok, sizeof(tok), "%s_data_del", uri); break; default: case CGI_REQ_GET: snprintf(tok, sizeof(tok), "%s_data_get", uri); break; } lses->dataer = strdup(tok); lses->render = strdup(uri); /* * tm_cache_browser */ node = hdf_get_obj(g_cfg, PRE_CFG_FILECACHE".0"); while (node != NULL) { if (reg_search(hdf_get_value(node, "uri", "NULL"), uri)) { lses->tm_cache_browser = hdf_get_int_value(node, "tm_cache", 0); break; } node = hdf_obj_next(node); } /* * DONE */ *ses = lses; return STATUS_OK; }
static NEOERR* _set_value (HDF *hdf, const char *name, const char *value, int dupl, int wf, int lnk, HDF_ATTR *attr, HDF **set_node) { NEOERR *err; HDF *hn, *hp, *hs; HDF hash_key; int x = 0; const char *s = name; const char *n = name; int count = 0; if (set_node != NULL) *set_node = NULL; if (hdf == NULL) { return nerr_raise(NERR_ASSERT, "Unable to set %s on NULL hdf", name); } /* HACK: allow setting of this node by passing an empty name */ if (name == NULL || name[0] == '\0') { /* handle setting attr first */ if (hdf->attr == NULL) { hdf->attr = attr; } else { _merge_attr(hdf->attr, attr); } /* set link flag */ if (lnk) hdf->link = 1; else hdf->link = 0; /* if we're setting ourselves to ourselves... */ if (hdf->value == value) { if (set_node != NULL) *set_node = hdf; return STATUS_OK; } if (hdf->alloc_value) { free(hdf->value); hdf->value = NULL; } if (value == NULL) { hdf->alloc_value = 0; hdf->value = NULL; } else if (dupl) { hdf->alloc_value = 1; hdf->value = strdup(value); if (hdf->value == NULL) return nerr_raise (NERR_NOMEM, "Unable to duplicate value %s for %s", value, name); } else { hdf->alloc_value = wf; hdf->value = (char *)value; } if (set_node != NULL) *set_node = hdf; return STATUS_OK; } n = name; s = strchr (n, '.'); x = (s != NULL) ? s - n : strlen(n); if (x == 0) { return nerr_raise(NERR_ASSERT, "Unable to set Empty component %s", name); } if (hdf->link) { char *new_name = (char *) malloc(strlen(hdf->value) + 1 + strlen(name) + 1); if (new_name == NULL) { return nerr_raise(NERR_NOMEM, "Unable to allocate memory"); } strcpy(new_name, hdf->value); strcat(new_name, "."); strcat(new_name, name); err = _set_value (hdf->top, new_name, value, dupl, wf, lnk, attr, set_node); free(new_name); return nerr_pass(err); } else { hn = hdf; } while (1) { /* examine cache to see if we have a match */ count = 0; hp = hn->last_hp; hs = hn->last_hs; if ((hs == NULL && hp == hn->child) || (hs && hs->next == hp)) { if (hp && hp->name && (x == hp->name_len) && !strncmp (hp->name, n, x)) { goto skip_search; } } hp = hn->child; hs = NULL; /* Look for a matching node at this level */ if (hn->hash != NULL) { hash_key.name = (char *)n; hash_key.name_len = x; hp = ne_hash_lookup(hn->hash, &hash_key); hs = hn->last_child; } else { while (hp != NULL) { if (hp->name && (x == hp->name_len) && !strncmp(hp->name, n, x)) { break; } hs = hp; hp = hp->next; count++; } } /* save in cache any value we found */ if (hp) { hn->last_hp = hp; hn->last_hs = hs; } skip_search: if (hp == NULL) { /* If there was no matching node at this level, we need to * allocate an intersitial node (or the actual node if we're * at the last part of the HDF name) */ if (s != NULL) { /* intersitial */ err = _alloc_hdf (&hp, n, x, NULL, 0, 0, hdf->top); } else { err = _alloc_hdf (&hp, n, x, value, dupl, wf, hdf->top); if (lnk) hp->link = 1; else hp->link = 0; hp->attr = attr; } if (err != STATUS_OK) return nerr_pass (err); if (hn->child == NULL) hn->child = hp; else hs->next = hp; hn->last_child = hp; /* This is the point at which we convert to a hash table * at this level, if we're over the count */ if (count > FORCE_HASH_AT && hn->hash == NULL) { err = _hdf_hash_level(hn); if (err) return nerr_pass(err); } else if (hn->hash != NULL) { err = ne_hash_insert(hn->hash, hp, hp); if (err) return nerr_pass(err); } } else if (s == NULL) { /* If there is a matching node and we're at the end of the HDF * name, then we update the value of the node */ /* handle setting attr first */ if (hp->attr == NULL) { hp->attr = attr; } else { _merge_attr(hp->attr, attr); } if (hp->value != value) { if (hp->alloc_value) { free(hp->value); hp->value = NULL; } if (value == NULL) { hp->alloc_value = 0; hp->value = NULL; } else if (dupl) { hp->alloc_value = 1; hp->value = strdup(value); if (hp->value == NULL) return nerr_raise (NERR_NOMEM, "Unable to duplicate value %s for %s", value, name); } else { hp->alloc_value = wf; hp->value = (char *)value; } } if (lnk) hp->link = 1; else hp->link = 0; } else if (hp->link) { char *new_name = (char *) malloc(strlen(hp->value) + strlen(s) + 1); if (new_name == NULL) { return nerr_raise(NERR_NOMEM, "Unable to allocate memory"); } strcpy(new_name, hp->value); strcat(new_name, s); err = _set_value (hdf->top, new_name, value, dupl, wf, lnk, attr, set_node); free(new_name); return nerr_pass(err); } /* At this point, we're done if there is not more HDF name space to * traverse */ if (s == NULL) break; /* Otherwise, we need to find the next part of the namespace */ n = s + 1; s = strchr (n, '.'); x = (s != NULL) ? s - n : strlen(n); if (x == 0) { return nerr_raise(NERR_ASSERT, "Unable to set Empty component %s", name); } hn = hp; } if (set_node != NULL) *set_node = hp; return STATUS_OK; }
static NEOERR* _hdf_read_string (HDF *hdf, const char **str, STRING *line, const char *path, int *lineno, int include_handle, int expect_end_brace) { NEOERR *err; HDF *lower; char *s; char *name, *value; HDF_ATTR *attr = NULL; while (**str != '\0') { /* Reset string length, but don't free the reserved buffer */ line->len = 0; err = _copy_line_advance(str, line); if (err) return nerr_pass(err); attr = NULL; (*lineno)++; s = line->buf; SKIPWS(s); if ((!strncmp(s, "#include ", 9) || !strncmp(s, "-include ", 9)) && include_handle != INCLUDE_IGNORE) { int required = !strncmp(s, "#include ", 9); if (include_handle == INCLUDE_ERROR) { return nerr_raise (NERR_PARSE, "[%d]: #include not supported in string parse", *lineno); } else if (include_handle < INCLUDE_MAX_DEPTH) { int l; s += 9; name = neos_strip(s); l = strlen(name); if (name[0] == '"' && name[l-1] == '"') { name[l-1] = '\0'; name++; } char fullpath[PATH_MAX]; if (name[0] != '/') { memset(fullpath, 0, PATH_MAX); char *p = strrchr(path, '/'); if (p == NULL) { char pwd[PATH_MAX]; memset(pwd, 0, PATH_MAX); getcwd(pwd, PATH_MAX); snprintf(fullpath, PATH_MAX, "%s/%s", pwd, name); } else { int dir_len = p - path + 1; snprintf(fullpath, PATH_MAX, "%s", path); snprintf(fullpath + dir_len, PATH_MAX - dir_len, "%s", name); } name = fullpath; } err = hdf_read_file_internal(hdf, name, include_handle + 1); if (err != STATUS_OK && required) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } } else { return nerr_raise (NERR_MAX_RECURSION, "[%d]: Too many recursion levels.", *lineno ); } } else if (s[0] == '#') { /* comment: pass */ } else if (s[0] == '}') /* up */ { s = neos_strip(s); if (strcmp(s, "}")) { err = nerr_raise(NERR_PARSE, "[%s:%d] Trailing garbage on line following }: %s", path, *lineno, line->buf); return err; } return STATUS_OK; } else if (s[0]) { /* Valid hdf name is [0-9a-zA-Z_.]+ */ int splice = *s == '@'; if (splice) s++; name = s; while (*s && (isalnum(*s) || *s == '_' || *s == '.' || *s == '*')) s++; SKIPWS(s); char num[16]; static int counter = 0; if (*name == '*') { snprintf(num, sizeof(num), "%d", counter++); name = num; } if (s[0] == '[') /* attributes */ { *s = '\0'; name = neos_strip(name); s++; err = parse_attr(&s, &attr); if (err) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } SKIPWS(s); } if (splice) { name = neos_strip(name); HDF *h = hdf_get_obj(hdf->top, name); if (h) { HDF *c = hdf_obj_child(h); while (c) { err = hdf_copy (hdf, hdf_obj_name(c), c); if (err != STATUS_OK) break; c = hdf_obj_next(c); } } if (err != STATUS_OK) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } } else if (s[0] == '=') /* assignment */ { *s = '\0'; name = neos_strip(name); s++; value = neos_strip(s); err = _set_value (hdf, name, value, 1, 1, 0, attr, NULL); if (err != STATUS_OK) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } } else if (s[0] == ':' && s[1] == '=') /* copy */ { *s = '\0'; name = neos_strip(name); s+=2; value = neos_strip(s); HDF *h = hdf_get_obj(hdf->top, value); if (!h) { err = nerr_raise(NERR_PARSE, "[%s:%d] Failed to copy a node that is not loaded " "yet: %s", path, *lineno, value); return err; } err = hdf_copy(hdf, name, h); if (err != STATUS_OK) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } } else if (s[0] == '!' && s[1] == '=') /* exec */ { *s = '\0'; name = neos_strip(name); s+=2; value = neos_strip(s); FILE *f = popen(value, "r"); if (f == NULL) { err = nerr_raise(NERR_PARSE, "[%s:%d] Failed to exec specified command: %s", path, *lineno, line->buf); return err; } char *content = _read_file(f); fclose(f); int len = strlen(content); if (len > 0 && content[len - 1] == '\n') { content[len - 1] = '\0'; // remove \n artifact } err = _set_value (hdf, name, content, 1, 1, 0, attr, NULL); free(content); if (err != STATUS_OK) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } } else if (s[0] == ':') /* link */ { *s = '\0'; name = neos_strip(name); s++; value = neos_strip(s); err = _set_value (hdf, name, value, 1, 1, 1, attr, NULL); if (err != STATUS_OK) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } } else if (s[0] == '{') /* deeper */ { *s = '\0'; name = neos_strip(name); lower = hdf_get_obj (hdf, name); if (lower == NULL) { err = _set_value (hdf, name, NULL, 1, 1, 0, attr, &lower); } else { err = _set_value (lower, NULL, lower->value, 1, 1, 0, attr, NULL); } if (err != STATUS_OK) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } err = _hdf_read_string (lower, str, line, path, lineno, include_handle, 1); if (err != STATUS_OK) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } } else if (s[0] == '<' && s[1] == '<') /* multi-line assignment */ { char *m; int msize = 0; int mmax = 128; int l; *s = '\0'; name = neos_strip(name); s+=2; value = neos_strip(s); l = strlen(value); if (l == 0) { err = nerr_raise(NERR_PARSE, "[%s:%d] No multi-assignment terminator given: %s", path, *lineno, line->buf); return err; } m = (char *) malloc (mmax * sizeof(char)); if (m == NULL) { return nerr_raise(NERR_NOMEM, "[%s:%d] Unable to allocate memory for multi-line assignment to %s", path, *lineno, name); } while (_copy_line (str, m+msize, mmax-msize) != 0) { (*lineno)++; if (!strncmp(value, m+msize, l) && isspace(m[msize+l])) { m[msize] = '\0'; break; } msize += strlen(m+msize); if (msize + l + 10 > mmax) { void *new_ptr; mmax += 128; new_ptr = realloc (m, mmax * sizeof(char)); if (new_ptr == NULL) { free(m); return nerr_raise(NERR_NOMEM, "[%s:%d] Unable to allocate memory for multi-line assignment to %s: size=%d", path, *lineno, name, mmax); } m = (char *) new_ptr; } } err = _set_value (hdf, name, m, 0, 1, 0, attr, NULL); if (err != STATUS_OK) { free (m); return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } } else { err = nerr_raise(NERR_PARSE, "[%s:%d] Unable to parse line %s", path, *lineno, line->buf); return err; } } } if (expect_end_brace) { err = nerr_raise(NERR_PARSE, "[%s:%d] Missing matching }", path, *lineno); return err; } return STATUS_OK; }
/* attributes are of the form [key1, key2, key3=value, key4="repr"] */ static NEOERR* parse_attr(char **str, HDF_ATTR **attr) { NEOERR *err = STATUS_OK; char *s = *str; char *k, *v; int k_l, v_l; STRING buf; char c; HDF_ATTR *ha, *hal = NULL; *attr = NULL; string_init(&buf); while (*s && *s != ']') { k = s; k_l = 0; v = NULL; v_l = 0; while (*s && isalnum(*s)) s++; k_l = s-k; if (*s == '\0' || k_l == 0) { _dealloc_hdf_attr(attr); return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str); } SKIPWS(s); if (*s == '=') { s++; SKIPWS(s); if (*s == '"') { s++; while (*s && *s != '"') { if (*s == '\\') { if (isdigit(*(s+1))) { s++; c = *s - '0'; if (isdigit(*(s+1))) { s++; c = (c * 8) + (*s - '0'); if (isdigit(*(s+1))) { s++; c = (c * 8) + (*s - '0'); } } } else { s++; if (*s == 'n') c = '\n'; else if (*s == 't') c = '\t'; else if (*s == 'r') c = '\r'; else c = *s; } err = string_append_char(&buf, c); } else { err = string_append_char(&buf, *s); } if (err) { string_clear(&buf); _dealloc_hdf_attr(attr); return nerr_pass(err); } s++; } if (*s == '\0') { _dealloc_hdf_attr(attr); string_clear(&buf); return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str); } s++; v = buf.buf; v_l = buf.len; } else { v = s; while (*s && *s != ' ' && *s != ',' && *s != ']') s++; if (*s == '\0') { _dealloc_hdf_attr(attr); return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str); } v_l = s-v; } } else { v = "1"; } ha = (HDF_ATTR*) calloc (1, sizeof(HDF_ATTR)); if (ha == NULL) { _dealloc_hdf_attr(attr); string_clear(&buf); return nerr_raise(NERR_NOMEM, "Unable to load attributes: %s", s); } if (*attr == NULL) *attr = ha; ha->key = _strndup(k, k_l); if (v) ha->value = _strndup(v, v_l); else ha->value = strdup(""); if (ha->key == NULL || ha->value == NULL) { _dealloc_hdf_attr(attr); string_clear(&buf); return nerr_raise(NERR_NOMEM, "Unable to load attributes: %s", s); } if (hal != NULL) hal->next = ha; hal = ha; string_clear(&buf); SKIPWS(s); if (*s == ',') { s++; SKIPWS(s); } } if (*s == '\0') { _dealloc_hdf_attr(attr); return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str); } *str = s+1; return STATUS_OK; }
static NEOERR* hdf_dump_cb(HDF *hdf, const char *prefix, int dtype, int lvl, void *rock, DUMPF_CB dump_cbf) { NEOERR *err; char *p, op; char ml[10] = "\nEOM\n"; int ml_len = strlen(ml); char whsp[256] = ""; if (dtype == DUMP_TYPE_PRETTY) { memset(whsp, ' ', 256); if (lvl > 127) lvl = 127; whsp[lvl*2] = '\0'; } if (hdf != NULL) hdf = hdf->child; while (hdf != NULL) { op = '='; if (hdf->value) { if (hdf->link) op = ':'; if (prefix && (dtype == DUMP_TYPE_DOTTED)) { err = dump_cbf(rock, "%s.%s", prefix, hdf->name); } else { err = dump_cbf(rock, "%s%s", whsp, hdf->name); } if (err) return nerr_pass (err); if (hdf->attr) { HDF_ATTR *attr = hdf->attr; char *v = NULL; err = dump_cbf(rock, " ["); if (err) return nerr_pass(err); while (attr != NULL) { if (attr->value == NULL || !strcmp(attr->value, "1")) err = dump_cbf(rock, "%s", attr->key); else { v = repr_string_alloc(attr->value); if (v == NULL) return nerr_raise(NERR_NOMEM, "Unable to repr attr %s value %s", attr->key, attr->value); err = dump_cbf(rock, "%s=%s", attr->key, v); free(v); } if (err) return nerr_pass(err); if (attr->next) { err = dump_cbf(rock, ", "); if (err) return nerr_pass(err); } attr = attr->next; } err = dump_cbf(rock, "] "); if (err) return nerr_pass(err); } if (strchr (hdf->value, '\n')) { int vlen = strlen(hdf->value); while (strstr(hdf->value, ml) || ((vlen > ml_len) && !strncmp(hdf->value + vlen - ml_len + 1, ml, strlen(ml) - 1))) { gen_ml_break(ml, sizeof(ml)); ml_len = strlen(ml); } if (hdf->value[strlen(hdf->value)-1] != '\n') err = dump_cbf(rock, " << %s%s%s", ml+1, hdf->value, ml); else err = dump_cbf(rock, " << %s%s%s", ml+1, hdf->value, ml+1); } else { err = dump_cbf(rock, " %c %s\n", op, hdf->value); } if (err) return nerr_pass (err); } if (hdf->child) { if (prefix && (dtype == DUMP_TYPE_DOTTED)) { p = (char *) malloc (strlen(hdf->name) + strlen(prefix) + 2); sprintf (p, "%s.%s", prefix, hdf->name); err = hdf_dump_cb (hdf, p, dtype, lvl+1, rock, dump_cbf); free(p); } else { if (hdf->name && (dtype != DUMP_TYPE_DOTTED)) { err = dump_cbf(rock, "%s%s {\n", whsp, hdf->name); if (err) return nerr_pass (err); err = hdf_dump_cb (hdf, hdf->name, dtype, lvl+1, rock, dump_cbf); if (err) return nerr_pass (err); err = dump_cbf(rock, "%s}\n", whsp); } else { err = hdf_dump_cb (hdf, hdf->name, dtype, lvl+1, rock, dump_cbf); } } if (err) return nerr_pass (err); } hdf = hdf->next; } return STATUS_OK; }