WsCompilerPtr ws_create(WsCompilerParams *params) { WsCompilerPtr compiler = ws_calloc(1, sizeof(*compiler)); if (compiler == NULL) return NULL; /* Store user params if specified. */ if (params) compiler->params = *params; /* Basic initialization. */ compiler->magic = COMPILER_MAGIC; if (compiler->params.stdout_cb == NULL) { compiler->params.stdout_cb = std_io; compiler->params.stdout_cb_context = stdout; } if (compiler->params.stderr_cb == NULL) { compiler->params.stderr_cb = std_io; compiler->params.stderr_cb_context = stderr; } return compiler; }
WsBc *ws_bc_alloc(WsBcStringEncoding string_encoding) { WsBc *bc = ws_calloc(1, sizeof(WsBc)); if (bc == NULL) return NULL; bc->string_encoding = string_encoding; return bc; }
WsHashPtr ws_hash_create(WsHashItemDestructor destructor, void *context) { WsHashPtr hash = ws_calloc(1, sizeof(*hash)); if (hash) { hash->destructor = destructor; hash->destructor_context = context; } return hash; }
WsFastMalloc *ws_f_create(size_t block_size) { WsFastMalloc *pool = ws_calloc(1, sizeof(WsFastMalloc)); if (pool == NULL) return NULL; pool->block_size = block_size; return pool; }
WsStream *ws_stream_new(void *context, WsStreamIOProc io, WsStreamFlushProc flush, WsStreamCloseProc close) { WsStream *stream = ws_calloc(1, sizeof(*stream)); if (stream == NULL) return NULL; stream->io = io; stream->flush = flush; stream->close = close; stream->context = context; return stream; }
void ws_pragma_use(WsCompilerPtr compiler, WsUInt32 line, char *identifier, WsUtf8String *url) { WsPragmaUse *u = ws_calloc(1, sizeof(*u)); WsPragmaUse *uold; /* Do we already know this pragma? */ uold = ws_hash_get(compiler->pragma_use_hash, identifier); if (uold) { ws_src_error(compiler, line, "redefinition of pragma `%s'", identifier); ws_src_error(compiler, uold->line, "`%s' previously defined here", identifier); goto error_cleanup; } if (u == NULL) goto error; u->line = line; /* Insert the URL to the byte-code module. */ if (!ws_bc_add_const_utf8_string(compiler->bc, &u->urlindex, url->data, url->len)) goto error; /* Add it to the use pragma hash. */ if (!ws_hash_put(compiler->pragma_use_hash, identifier, u)) goto error; /* Cleanup. */ ws_lexer_free_block(compiler, identifier); ws_lexer_free_utf8(compiler, url); return; /* Error handling. */ error: ws_error_memory(compiler); error_cleanup: ws_free(u); ws_lexer_free_block(compiler, identifier); ws_lexer_free_utf8(compiler, url); }
WsPragmaMetaBody *ws_pragma_meta_body(WsCompilerPtr compiler, WsUtf8String *property_name, WsUtf8String *content, WsUtf8String *scheme) { WsPragmaMetaBody *mb = ws_calloc(1, sizeof(*mb)); if (mb == NULL) { ws_error_memory(compiler); return NULL; } mb->property_name = property_name; mb->content = content; mb->scheme = scheme; return mb; }
WsStream *ws_stream_new_data_input(const unsigned char *data, size_t data_len) { WsStreamDataInputCtx *ctx = ws_calloc(1, sizeof(*ctx)); WsStream *stream; if (ctx == NULL) return NULL; ctx->data = data; ctx->data_len = data_len; stream = ws_stream_new(ctx, data_input, NULL, data_close); if (stream == NULL) /* The stream creation failed. Close the stream context. */ data_close(ctx); return stream; }
WsBool ws_hash_put(WsHashPtr hash, const char *name, void *data) { WsHashItem *i; size_t h = count_hash(name); for (i = hash->items[h]; i; i = i->next) { if (strcmp(i->name, name) == 0) { /* Found it. */ /* Destroy the old item */ if (hash->destructor) (*hash->destructor)(i->data, hash->destructor_context); i->data = data; return WS_FALSE; } } /* Must create a new mapping. */ i = ws_calloc(1, sizeof(*i)); if (i == NULL) return WS_FALSE; i->name = ws_strdup(name); if (i->name == NULL) { ws_free(i); return WS_FALSE; } i->data = data; /* Link it to our hash. */ i->next = hash->items[h]; hash->items[h] = i; return WS_TRUE; }
WsStream *ws_stream_new_file(FILE *fp, WsBool output, WsBool close) { WsStreamFileCtx *ctx = ws_calloc(1, sizeof(*ctx)); WsStream *stream; if (ctx == NULL) return NULL; ctx->fp = fp; ctx->close_fp = close; if (output) stream = ws_stream_new(ctx, file_output, file_flush, file_close); else stream = ws_stream_new(ctx, file_input, file_flush, file_close); if (stream == NULL) /* The stream creation failed. Close the stream context. */ file_close(ctx); return stream; }
WsFunctionHash *ws_function_hash(WsCompilerPtr compiler, char *name) { WsFunctionHash *i = ws_hash_get(compiler->functions_hash, name); if (i) return i; /* Must create a new mapping. */ i = ws_calloc(1, sizeof(*i)); if (i == NULL) { ws_error_memory(compiler); return NULL; } if (!ws_hash_put(compiler->functions_hash, name, i)) { ws_free(i); ws_error_memory(compiler); return NULL; } return i; }
WsNamespace *ws_variable_define(WsCompilerPtr compiler, WsUInt32 line, WsBool variablep, char *name) { WsNamespace *ns; /* Is the symbol already defined? */ ns = ws_hash_get(compiler->variables_hash, name); if (ns) { ws_src_error(compiler, line, "redeclaration of `%s'", name); ws_src_error(compiler, ns->line, "`%s' previously declared here", name); return NULL; } /* Can we still define more variables? */ if (compiler->next_vindex > 255) { /* No we can't. */ ws_src_error(compiler, line, "too many local variables"); return NULL; } ns = ws_calloc(1, sizeof(*ns)); if (ns == NULL) { ws_error_memory(compiler); return NULL; } ns->line = line; ns->vindex = compiler->next_vindex++; if (!ws_hash_put(compiler->variables_hash, name, ns)) { ws_free(ns); ws_error_memory(compiler); return NULL; } return ns; }
WsBc *ws_bc_decode(const unsigned char *data, size_t data_len) { WsBc *bc = ws_bc_alloc(WS_BC_STRING_ENC_ISO_8859_1); WsByte b; WsUInt32 ui32; WsUInt16 ui16, j; WsUInt16 ui16b; WsUInt8 ui8, num_functions, k, l; WsInt8 i8; WsInt16 i16; WsInt32 i32; WsIeee754Result ieee754; unsigned char *ucp; size_t decoded; /* Decode the byte-code header. */ decoded = ws_decode_buffer(data, data_len, WS_ENC_BYTE, &b, WS_ENC_MB_UINT32, &ui32, WS_ENC_END); if (!decoded || b != WS_BC_VERSION || ui32 != data_len - decoded) /* This is not a valid (or supported) byte-code header. */ goto error; WS_UPDATE_DATA; /* Constant pool. */ decoded = ws_decode_buffer(data, data_len, WS_ENC_MB_UINT16, &ui16, WS_ENC_MB_UINT16, &ui16b, WS_ENC_END); if (!decoded) goto error; bc->string_encoding = ui16b; bc->constants = ws_calloc(ui16, sizeof(WsBcConstant)); if (bc->constants == NULL) goto error; bc->num_constants = ui16; WS_UPDATE_DATA; for (j = 0; j < bc->num_constants; j++) { WsBcConstant *c = &bc->constants[j]; decoded = ws_decode_buffer(data, data_len, WS_ENC_UINT8, &ui8, WS_ENC_END); if (decoded != 1) goto error; WS_UPDATE_DATA; switch (ui8) { case WS_BC_CONST_INT8: decoded = ws_decode_buffer(data, data_len, WS_ENC_INT8, &i8, WS_ENC_END); if (decoded != 1) goto error; WS_UPDATE_DATA; c->type = WS_BC_CONST_TYPE_INT; c->u.v_int = i8; break; case WS_BC_CONST_INT16: decoded = ws_decode_buffer(data, data_len, WS_ENC_INT16, &i16, WS_ENC_END); if (decoded != 2) goto error; WS_UPDATE_DATA; c->type = WS_BC_CONST_TYPE_INT; c->u.v_int = i16; break; case WS_BC_CONST_INT32: decoded = ws_decode_buffer(data, data_len, WS_ENC_INT32, &i32, WS_ENC_END); if (decoded != 4) goto error; WS_UPDATE_DATA; c->type = WS_BC_CONST_TYPE_INT; c->u.v_int = i32; break; case WS_BC_CONST_FLOAT32: decoded = ws_decode_buffer(data, data_len, WS_ENC_DATA, &ucp, (size_t) 4, WS_ENC_END); if (decoded != 4) goto error; WS_UPDATE_DATA; ieee754 = ws_ieee754_decode_single(ucp, &c->u.v_float); switch (ieee754) { case WS_IEEE754_OK: c->type = WS_BC_CONST_TYPE_FLOAT32; break; case WS_IEEE754_NAN: c->type = WS_BC_CONST_TYPE_FLOAT32_NAN; break; case WS_IEEE754_POSITIVE_INF: c->type = WS_BC_CONST_TYPE_FLOAT32_POSITIVE_INF; break; case WS_IEEE754_NEGATIVE_INF: c->type = WS_BC_CONST_TYPE_FLOAT32_NEGATIVE_INF; break; } break; case WS_BC_CONST_UTF8_STRING: decoded = ws_decode_buffer(data, data_len, WS_ENC_MB_UINT32, &ui32, WS_ENC_END); if (decoded == 0) goto error; WS_UPDATE_DATA; c->type = WS_BC_CONST_TYPE_UTF8_STRING; c->u.v_string.len = ui32; decoded = ws_decode_buffer(data, data_len, WS_ENC_DATA, &ucp, c->u.v_string.len, WS_ENC_END); if (decoded != ui32) goto error; WS_UPDATE_DATA; c->u.v_string.data = ws_memdup(ucp, ui32); if (c->u.v_string.data == NULL) goto error; /* Check the validity of the data. */ if (!ws_utf8_verify(c->u.v_string.data, c->u.v_string.len, &c->u.v_string.num_chars)) goto error; break; case WS_BC_CONST_EMPTY_STRING: c->type = WS_BC_CONST_TYPE_EMPTY_STRING; break; case WS_BC_CONST_EXT_ENC_STRING: ws_fatal("external character encoding not implemented yet"); break; default: /* Reserved. */ goto error; break; } } /* Pragma pool. */ decoded = ws_decode_buffer(data, data_len, WS_ENC_MB_UINT16, &ui16, WS_ENC_END); if (!decoded) goto error; bc->pragmas = ws_calloc(ui16, sizeof(WsBcPragma)); if (bc->pragmas == NULL) goto error; bc->num_pragmas = ui16; WS_UPDATE_DATA; for (j = 0; j < bc->num_pragmas; j++) { WsBcPragma *p = &bc->pragmas[j]; decoded = ws_decode_buffer(data, data_len, WS_ENC_UINT8, &ui8, WS_ENC_END); if (decoded != 1) goto error; WS_UPDATE_DATA; p->type = ui8; switch (ui8) { case WS_BC_PRAGMA_ACCESS_DOMAIN: decoded = ws_decode_buffer(data, data_len, WS_ENC_MB_UINT16, &p->index_1, WS_ENC_END); if (!decoded) goto error; WS_CHECK_STRING(p->index_1); break; case WS_BC_PRAGMA_ACCESS_PATH: decoded = ws_decode_buffer(data, data_len, WS_ENC_MB_UINT16, &p->index_1, WS_ENC_END); if (!decoded) goto error; WS_CHECK_STRING(p->index_1); break; case WS_BC_PRAGMA_USER_AGENT_PROPERTY: decoded = ws_decode_buffer(data, data_len, WS_ENC_MB_UINT16, &p->index_1, WS_ENC_MB_UINT16, &p->index_2, WS_ENC_END); if (!decoded) goto error; WS_CHECK_STRING(p->index_1); WS_CHECK_STRING(p->index_2); break; case WS_BC_PRAGMA_USER_AGENT_PROPERTY_AND_SCHEME: decoded = ws_decode_buffer(data, data_len, WS_ENC_MB_UINT16, &p->index_1, WS_ENC_MB_UINT16, &p->index_2, WS_ENC_MB_UINT16, &p->index_3, WS_ENC_END); if (!decoded) goto error; WS_CHECK_STRING(p->index_1); WS_CHECK_STRING(p->index_2); WS_CHECK_STRING(p->index_3); break; default: goto error; break; } WS_UPDATE_DATA; } /* Function pool. */ decoded = ws_decode_buffer(data, data_len, WS_ENC_UINT8, &num_functions, WS_ENC_END); if (decoded != 1) goto error; WS_UPDATE_DATA; /* Function names. */ decoded = ws_decode_buffer(data, data_len, WS_ENC_UINT8, &ui8, WS_ENC_END); if (decoded != 1) goto error; WS_UPDATE_DATA; if (ui8) { /* We have function names. */ bc->function_names = ws_calloc(ui8, sizeof(WsBcFunctionName)); if (bc->function_names == NULL) goto error; bc->num_function_names = ui8; for (k = 0; k < bc->num_function_names; k++) { WsBcFunctionName *n = &bc->function_names[k]; decoded = ws_decode_buffer(data, data_len, WS_ENC_UINT8, &n->index, WS_ENC_UINT8, &ui8, WS_ENC_END); if (decoded != 2) goto error; WS_UPDATE_DATA; decoded = ws_decode_buffer(data, data_len, WS_ENC_DATA, &ucp, (size_t) ui8, WS_ENC_END); if (decoded != ui8) goto error; WS_UPDATE_DATA; n->name = ws_memdup(ucp, ui8); if (n->name == NULL) goto error; /* Check the validity of the name. */ if (!ws_utf8_verify((unsigned char *) n->name, ui8, NULL)) goto error; /* Just check that the data contains only valid characters. */ for (l = 0; l < ui8; l++) { unsigned int ch = (unsigned char) n->name[l]; if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ch == '_' || (l > 0 && ('0' <= ch && ch <= '9'))) /* Ok. */ continue; /* Invalid character in the function name. */ goto error; } /* Is the index valid? */ if (n->index >= num_functions) goto error; } } /* Functions. */ if (num_functions) { /* We have functions. */ bc->functions = ws_calloc(num_functions, sizeof(WsBcFunction)); if (bc->functions == NULL) goto error; bc->num_functions = num_functions; for (k = 0; k < bc->num_functions; k++) { WsBcFunction *f = &bc->functions[k]; decoded = ws_decode_buffer(data, data_len, WS_ENC_UINT8, &f->num_arguments, WS_ENC_UINT8, &f->num_locals, WS_ENC_MB_UINT32, &f->code_size, WS_ENC_END); if (!decoded) goto error; WS_UPDATE_DATA; decoded = ws_decode_buffer(data, data_len, WS_ENC_DATA, &ucp, f->code_size, WS_ENC_END); if (decoded != f->code_size) goto error; WS_UPDATE_DATA; if (f->code_size) { /* It is not an empty function. */ f->code = ws_memdup(ucp, f->code_size); if (f->code == NULL) goto error; } } } /* Did we process it all? */ if (data_len != 0) goto error; /* All done. */ return bc; /* * Error handling. */ error: ws_bc_free(bc); return NULL; }
WsUtf8String *ws_utf8_alloc() { return ws_calloc(1, sizeof(WsUtf8String)); }
WsBuffer *ws_buffer_alloc() { return ws_calloc(1, sizeof(WsBuffer)); }