void s3d_fnt_load_info(s3d_fnt_info *info, const char *path) { { info->line_height = -1; info->chars = 0; } int ichar = -1; static char path_buf[PATH_MAX]; s3d_strarrjoin(path_buf, { path, "/info" }); char *lines = s3d_read_file(path_buf, 1, 0); s3d_streachline(lines, line, line_no, { char *lptr = line; #define abort_parse(message, more...) \ abort_because( \ "%s:%d: " message ": %s", \ path_buf, line_no, ##more, line \ ) #define parse_tag(name) s3d_strconsume(&lptr, name " ") #define parse_attr_tok(name) { \ s3d_strskip(&lptr, " "); \ \ if(!s3d_strconsume(&lptr, name "=")) { \ abort_parse("Expected '" name "=' token"); \ } \ } #define parse_tok(tok) \ s3d_strskip(&lptr, " "); \ \ if(!s3d_strconsume(&lptr, tok)) { \ abort_parse("Expected '" tok "' token"); \ } #define parse_long(dst, name) { \ errno = 0; \ \ dst = strtol(lptr, &lptr, 10); \ \ if(errno) { \ abort_parse("Bad " name " value"); \ } \ } #define parse_eol() \ if(!s3d_strempty(lptr)) { \ abort_parse("Trailing characters"); \ } if(parse_tag("common")) { parse_attr_tok("lineHeight"); parse_long(info->line_height, "line height"); parse_attr_tok("base"); parse_long(info->base, "base"); parse_attr_tok("scaleW"); parse_long(info->scale_w, "scale width"); parse_attr_tok("scaleH"); parse_long(info->scale_h, "scale height"); parse_tok("pages=1"); parse_tok("packed=0"); parse_tok("alphaChnl=1"); parse_tok("redChnl=4"); parse_tok("greenChnl=4"); parse_tok("blueChnl=4"); parse_eol(); } else if(parse_tag("chars")) { parse_attr_tok("count"); parse_long(info->num_chars, "char count"); parse_eol(); if(info->num_chars > 0) { s3d_mallocptr(info->chars, info->num_chars); } ichar = 0; } else if(parse_tag("char")) { if(ichar == -1) { abort_parse("char tag before chars tag"); } if(ichar >= info->num_chars) { abort_parse( "Too many char tags (more than %d)", info->num_chars ); } s3d_fnt_char_info *cptr = &info->chars[ichar]; parse_attr_tok("id"); parse_long(cptr->id, "ID"); parse_attr_tok("x"); parse_long(cptr->x, "X"); parse_attr_tok("y"); parse_long(cptr->y, "Y"); parse_attr_tok("width"); parse_long(cptr->w, "width"); parse_attr_tok("height"); parse_long(cptr->h, "height"); parse_attr_tok("xoffset"); parse_long(cptr->xoff, "X offset"); parse_attr_tok("yoffset"); parse_long(cptr->yoff, "Y offset"); parse_attr_tok("xadvance"); parse_long(cptr->xadv, "X advance"); parse_tok("page=0"); parse_tok("chnl=15"); parse_eol(); ++ichar; } else { abort_parse("Invalid tag"); } }) #undef parse_tag #undef parse_attr_tok #undef parse_tok #undef parse_long #undef parse_eol #undef abort_parse if(info->line_height == -1) {
int init_globals(char *config_file) { FILE *in_config; char buf[1][30], **ptr1; char line[MAX_LINE]; char space[4] = "\n\t "; char *token; int err = 0; #ifdef _PRINT fprintf(log_file, "ENTER[init_globals].\n"); #endif in_config = fopen(config_file, "r"); if (in_config == NULL) { fprintf(stderr, "Cannot open configuration file=[%s]:[%s]. Exiting.\n", config_file, strerror(errno)); return 1; } ptr1 = (char **)&buf[0]; while (fgets(line, MAX_LINE, in_config) != NULL) { fprintf(stderr, "%s\n", line); if (line[0] == '#' || line[0] == '\n' || line[0] == ' ') continue; #if !defined (UNIX) && !defined (OSX) token = strtok_s(line, space, ptr1); #else token = strtok_r(line, space, ptr1); #endif if (!strncmp(token, "DIFFUSION_COEFFICIENT", strlen("DIFFUSION_COEFFICIENT"))) { //token = strtok_s(NULL,space,ptr1); err = parse_tok(ptr1,&token,space); e.diffusion_coefficient = strtod(token, NULL); /* DIFFUSION_COEFFICIENT can never be 0 as it is used in divisions */ if (e.diffusion_coefficient < 1.0) e.diffusion_coefficient = 1.0; fprintf(stderr, "DIFFUSION_COEFFICIENT=%.0f\n", e.diffusion_coefficient); } else if (!strncmp(token, "EDDY_CONST", strlen("EDDY_CONST"))) { //token = strtok_r(NULL,space,ptr1); err = parse_tok(ptr1,&token,space); e.eddy_constant = strtod(token, NULL); fprintf(stderr, "EDDY_CONST=%.2f\n", e.eddy_constant); } else if (!strncmp(token, "FALL_TIME_THRESHOLD", strlen("FALL_TIME_THRESHOLD"))) { //token = strtok_r(NULL,space,ptr1); err = parse_tok(ptr1,&token,space); e.fall_time_threshold = strtod(token, NULL); fprintf(stderr, "FALL_TIME_THRESHOLD=%.0f\n", e.fall_time_threshold); } else if (!strncmp(token, "LITHIC_DENSITY", strlen("LITHIC_DENSITY"))) { //token = strtok_r(NULL,space,ptr1); err = parse_tok(ptr1,&token,space); e.lithic_density = strtod(token, NULL); fprintf(stderr, "LITHIC_DENSITY=%.0f\n", e.lithic_density); } else if (!strncmp(token, "PUMICE_DENSITY", strlen("PUMICE_DENSITY"))) { //token = strtok_r(NULL,space,ptr1); err = parse_tok(ptr1,&token,space); e.pumice_density = strtod(token, NULL); fprintf(stderr, "PUMICE_DENSITY=%.0f\n", e.pumice_density); } else if (!strncmp(token, "PART_STEPS", strlen("PART_STEPS"))) { //token = strtok_r(NULL, space, ptr1); err = parse_tok(ptr1,&token,space); PART_STEPS = (int)atof(token); fprintf(stderr, "PART_STEPS = %d\n", PART_STEPS); } else if (!strncmp(token, "COL_STEPS", strlen("COL_STEPS"))) { //token = strtok_r(NULL, space, ptr1); err = parse_tok(ptr1,&token,space); COL_STEPS = (int)atof(token); fprintf(stderr, "COL_STEPS = %d\n", COL_STEPS); } else if (!strncmp(token, "PLUME_MODEL", strlen("PLUME_MODEL"))) { //token = strtok_r(NULL,space,ptr1); err = parse_tok(ptr1,&token,space); e.plume_model = (int)atof(token); if (e.plume_model == 0) { pdf = plume_pdf0; fprintf(stderr, "PLUME_MODEL=[%d]%s\n", e.plume_model, "Uniform Distribution with threshold"); } else if (e.plume_model == 1) { pdf = plume_pdf1; fprintf(stderr, "PLUME_MODEL=[%d]%s\n", e.plume_model, "log-normal Distribution using beta"); } else if (e.plume_model == 2) { pdf = plume_pdf2; fprintf(log_file, "PLUME_MODEL=[%d]%s\n", e.plume_model, "Beta Distribution with ALPHA and BETA parameteres"); } } else if (!strncmp(token, "PLUME_RATIO", strlen("PLUME_RATIO"))) { //token = strtok_r(NULL, space, ptr1); err = parse_tok(ptr1,&token,space); e.plume_ratio = strtod(token, NULL); if (!e.plume_model) fprintf(stderr, "PLUME_RATIO = %.2f\n", e.plume_ratio); } else if (!strncmp(token, "ALPHA", strlen("ALPHA"))) { //token = strtok_r(NULL, space, ptr1); err = parse_tok(ptr1,&token,space); e.alpha = strtod(token, NULL); if (e.plume_model==2) fprintf(stderr, "ALPHA = %g\n", e.alpha); } else if (!strncmp(token, "BETA", strlen("BETA"))) { //token = strtok_r(NULL, space, ptr1); err = parse_tok(ptr1,&token,space); e.beta = strtod(token, NULL); if (e.plume_model==2) fprintf(stderr, "BETA = %g\n", e.beta); } else if (!strncmp(token, "PLUME_HEIGHT", strlen("PLUME_HEIGHT"))) { //token = strtok_r(NULL, space, ptr1); err = parse_tok(ptr1,&token,space); e.max_plume_elevation = strtod(token, NULL); fprintf(stderr, "PLUME_HEIGHT = %.0f\n", e.max_plume_elevation); } else if (!strncmp(token, "ERUPTION_MASS", strlen("ERUPTION_MASS"))) { //token = strtok_r(NULL, space, ptr1); err = parse_tok(ptr1,&token,space); e.total_ash_mass = strtod(token, NULL); fprintf(stderr, "ERUPTION_MASS = %g\n", e.total_ash_mass); } else if (!strncmp(token, "MAX_GRAINSIZE", strlen("MAX_GRAINSIZE"))) { //token = strtok_r(NULL, space, ptr1); err = parse_tok(ptr1,&token,space); e.min_phi = strtod(token, NULL); fprintf(stderr, "MAX_GRAINSIZE = %g (phi)\n", e.min_phi); } else if (!strncmp(token, "MIN_GRAINSIZE", strlen("MIN_GRAINSIZE"))) { //token = strtok_r(NULL, space, ptr1); err = parse_tok(ptr1,&token,space); e.max_phi = strtod(token, NULL); fprintf(stderr, "MIN_GRAINSIZE = %g (phi)\n", e.max_phi); } else if (!strncmp(token, "MEDIAN_GRAINSIZE", strlen("MEDIAN_GRAINSIZE"))) { //token = strtok_r(NULL, space, ptr1); err = parse_tok(ptr1,&token,space); e.mean_phi = strtod(token, NULL); fprintf(stderr, "MEDIAN_GRAINSIZE = %g (phi)\n", e.mean_phi); } else if (!strncmp(token, "STD_GRAINSIZE", strlen("STD_GRAINSIZE"))) { //token = strtok_r(NULL, space, ptr1); err = parse_tok(ptr1,&token,space); e.sigma_phi = strtod(token, NULL); /* if (STD_GRAINSIZE < 1.0) STD_GRAINSIZE = 1.0; */ fprintf(stderr, "STD_GRAINSIZE = %g (phi)\n", e.sigma_phi); } else if (!strncmp(token, "VENT_EASTING", strlen("VENT_EASTING"))) { //token = strtok_r(NULL, space, ptr1); err = parse_tok(ptr1,&token,space); e.vent_easting = strtod(token, NULL); fprintf(stderr, "VENT_EASTING = %.0f\n", e.vent_easting); } else if (!strncmp(token, "VENT_NORTHING", strlen("VENT_NORTHING"))) { //token = strtok_r(NULL, space, ptr1); err = parse_tok(ptr1,&token,space); e.vent_northing = strtod(token, NULL); fprintf(stderr, "VENT_NORTHING = %.0f\n", e.vent_northing); } else if (!strncmp(token, "VENT_ELEVATION", strlen("VENT_ELEVATION"))) { //token = strtok_r(NULL, space, ptr1); err = parse_tok(ptr1,&token,space); e.vent_elevation = strtod(token, NULL); fprintf(stderr, "VENT_ELEVATION = %.0f\n", e.vent_elevation); } else continue; } (void) fclose(in_config); #ifdef _PRINT fprintf(log_file, "EXIT[init_globals].\n"); #endif return 0; }
/* * Process a request from our HTTP client. The main server loop calls this * when the socket has data ready to read. */ int TadsHttpServerThread::process_request() { StringRef *hdrs = new StringRef(1024); TadsHttpRequestHeader *hdr_list = 0, *hdr_tail = 0; TadsHttpRequest *req = 0; char *verb; size_t verb_len; char *resource_name; size_t res_name_len; int ok = FALSE; long ofs; char *p, *hbody; StringRef *body = 0; int overflow = FALSE; long hbodylen; const char *hcl, *hte; /* content-length, transfer-encoding */ /* * Read the header. We read data into our buffer until we find a * double CR-LF sequence, indicating the end of the header. */ if ((ofs = read_to_nl(hdrs, 0, 0, 4)) < 0) goto done; /* the body, if any, starts after the double line break */ hbody = hdrs->get() + ofs; hbodylen = hdrs->getlen() - ofs; /* truncate the headers to the CR-LF-CR-LF sequence */ hdrs->truncate(ofs - 2); /* * Parse the main verb in the header - get the method and the resource * ID. The format is: * *. <space>* VERB <space>+ RESOURCE <space>+ HTTP-VERSION <CRLF> */ p = hdrs->get(); parse_tok(p, verb, verb_len); parse_tok(p, resource_name, res_name_len); /* now parse the remaining headers */ TadsHttpRequestHeader::parse_headers(hdr_list, hdr_tail, FALSE, hdrs, 0); /* * Check to see if there's a message body. There is if there's a * content-length or transfer-encoding header. */ hcl = hdr_list->find("content-length"); hte = hdr_list->find("transfer-encoding"); if (hcl != 0 || hte != 0) { /* * There's a content body. If there's a content-length field, * pre-allocate a chunk of memory, then read the number of bytes * indicated. If it's a chunked transfer, read it in pieces. */ if (hcl != 0) { /* get the length */ long hclval = atol(hcl); /* if it's non-zero, read the content */ if (hclval != 0) { /* if this exceeds the size limit, abort */ if (upload_limit != 0 && hclval > upload_limit) { /* set the overflow flag, discard the input, and abort */ overflow = TRUE; read(0, 0, hclval, 5000); goto done_with_upload; } /* allocate the buffer; it's initially empty */ body = new StringRef(hclval); /* copy any portion of the body we've already read */ if (hbodylen != 0) { /* limit this to the declared size */ if (hbodylen > hclval) hbodylen = hclval; /* copy the data */ body->append(hbody, hbodylen); /* deduct the remaining size */ hclval -= hbodylen; } /* read the body */ if (hclval != 0 && read(body->getend(), hclval, hclval, 5000) < 0) { send_simple(S_http_400, "text/html", "Error receiving request message body"); goto done; } /* set the body length */ body->addlen(hclval); } } else if (stricmp(hte, "chunked") == 0) { /* set up a string buffer for the content */ const long initlen = 32000; body = new StringRef(hbodylen > initlen ? hbodylen : initlen); /* if we've already read some body text, copy it to the buffer */ if (hbodylen != 0) body->append(hbody, hbodylen); /* keep going until we reach the end marker */ for (ofs = 0 ; ; ) { /* read to the first newline */ long nlofs = read_to_nl(body, ofs, 0, 2); if (nlofs < 0) goto done; /* get the chunk length */ long chunklen = strtol(body->get() + ofs, 0, 16); /* * We're done with the chunk length. Move any read-ahead * content down in memory so that it directly abuts the * preceding chunk, so that when we're done we'll have the * content assembled into one contiguous piece. */ long ralen = body->getlen() - nlofs; if (ralen > 0) memmove(body->get() + ofs, body->get() + nlofs, body->getlen() - nlofs); /* stop at the end of the read-ahead portion */ body->truncate(ofs + ralen); /* if the chunk length is zero, we're done */ if (chunklen == 0) break; /* check if this would overflow our upload size limit */ if (upload_limit != 0 && !overflow && body->getlen() + chunklen > upload_limit) { /* flag the overflow, but keep reading the content */ overflow = TRUE; } /* * figure the remaining read size for this chunk, after any * read-ahead portion */ long chunkrem = chunklen - ralen; /* * if we've already overflowed, read and discard the chunk; * otherwise read it into our buffer */ if (chunkrem + 2 <= 0) { /* * We've already read ahead by enough to cover the next * chunk and the newline at the end. Go in and delete * the newline (or as much of it as exists). Start by * getting the offset of the newline: it's just after * the current chunk, which starts at 'ofs' and runs * for 'chunklen'. */ nlofs = ofs + chunklen; /* * if we haven't yet read the full newline sequence, do * so now */ if (ralen - chunklen < 2) { long nllen = 2 - (ralen - chunklen); body->ensure(nllen); if (read(body->getend(), nllen, nllen, 30000) < 0) { send_simple(S_http_400, "text/html", "Error receiving request message chunk"); goto done; } } /* * if there's anything after the newline, move it down * to overwrite the newline */ if (ralen - chunklen > 2) { /* move the bytes */ memmove(body->get() + nlofs, body->get() + nlofs + 2, ralen - chunklen - 2); /* adjust the size for the closed gap */ body->truncate(body->getlen() - 2); } /* resume from after the newline */ ofs = nlofs; } else if (overflow) { /* overflow - discard the chunk size (plus the CR-LF) */ if (read(0, 0, chunkrem+2, 30000) < 0) goto done; /* clear the buffer */ body->truncate(0); ofs = 0; } else { /* ensure the buffer is big enough */ body->ensure(chunkrem + 2); /* read the chunk, plus the CR-LF that follows */ if (read(body->getend(), chunkrem + 2, chunkrem + 2, 30000) < 0) { send_simple(S_http_400, "text/html", "Error receiving request message chunk"); goto done; } /* count the amount we just read in the buffer length */ body->addlen(chunkrem + 2); /* verify that the last two bytes are indeed CR-LF */ if (memcmp(body->getend() - 2, "\r\n", 2) != 0) { send_simple(S_http_400, "text/html", "Error in request message chunk"); goto done; } /* * move past the chunk for the next read, minus the * CR-LF that follows the chunk - that isn't part of * the data, but just part of the protocol */ ofs = body->getlen() - 2; body->truncate(ofs); } } /* * Read to the closing blank line. We've just passed one * newline, following the '0' end length marker, so we're in * state 2. We could have either another newline following, or * "trailers" (more headers, following the content body). */ long nlofs = read_to_nl(body, ofs, 2, 4); if (nlofs < 0) goto done; /* * if we have more than just the closing blank line, we have * trailers - append them to the headers */ if (nlofs > ofs + 2) { TadsHttpRequestHeader::parse_headers( hdr_list, hdr_tail, TRUE, body, ofs); } /* * the trailers (if any) and closing newline aren't part of the * content - clip them out of the body */ body->truncate(ofs); } else { /* * Other combinations of these headers are illegal. Send an * error and abort. */ send_simple(S_http_400, "text/html", "<html><title>Bad Request</title>" "<h1>Bad Request</h1>" "This server does not accept the specified " "transfer-encoding."); goto done; } done_with_upload: /* done with the upload - check for overflow */ if (overflow) { /* release the body, if present */ if (body != 0) { body->release_ref(); body = 0; } } } /* create a message object for the request */ req = new TadsHttpRequest( this, verb, verb_len, hdrs, hdr_list, body, overflow, resource_name, res_name_len, listener->get_shutdown_evt()); /* we've handed over the header list to the request */ hdr_list = 0; /* send it to the main thread, and wait for the reply */ if (queue->send(req, OS_FOREVER)) { /* * success - the server will already have sent the reply, so we're * done */ } else if (queue->is_quitting()) { /* failed due to server shutdown */ send_simple(S_http_503, "text/html", S_http_503_quitting_body); } else { /* 'send' failed - return an internal server error */ send_simple(S_http_500, "text/html", S_http_500_body); } /* we're done with the request */ req->release_ref(); /* success */ ok = TRUE; done: /* release the message body buffer */ if (body != 0) body->release_ref(); /* release the header buffer */ hdrs->release_ref(); /* delete the header list */ if (hdr_list != 0) delete hdr_list; /* return the success/failure indication */ return ok; }