static int t13Support(cffCtx h) { /* Change op stack size */ MEM_FREE(h, h->stack.array); MEM_FREE(h, h->stack.type); h->stack.max = T13_MAX_OP_STACK; h->stack.array = MEM_NEW(h, T13_MAX_OP_STACK * sizeof(StkElement)); h->stack.type = MEM_NEW(h, T13_MAX_OP_STACK); return 1; }
void GDEFNew(hotCtx g) { GDEFCtx h = MEM_NEW(g, sizeof(struct GDEFCtx_)); /* Link contexts */ h->g = g; g->ctx.GDEF = h; dnaINIT(g->dnaCtx, h->glyphClasess, 50, 200); dnaINIT(g->dnaCtx, h->attachEntries, 50, 200); dnaINIT(g->dnaCtx, h->ligCaretEntries, 50, 200); dnaINIT(g->dnaCtx, h->markAttachClasses, 50, 200); dnaINIT(g->dnaCtx, h->markSetClasses, 50, 200); h->offset = 0; h->tbl.GlyphClassDefOffset = 0; h->tbl.AttachTableOffset = 0; h->tbl.LigCaretTableOffset = 0; h->tbl.MarkClassDefOffset = 0; h->tbl.MarkGlyphSetsDefOffset = 0; h->glyphClassTable = NULL; h->attachTable.otl = NULL; h->attachTable.GlyphCount = 0; h->ligCaretTable.otl = NULL; h->ligCaretTable.LigGlyphCount = 0; h->markAttachClassTable = NULL; }
/* Initialize module */ void t13New(tcCtx g) { t13Ctx h = MEM_NEW(g, sizeof(struct t13Ctx_)); /* Link contexts */ h->g = g; g->ctx.t13 = h; }
void maxpNew(hotCtx g) { maxpCtx h = MEM_NEW(g, sizeof(struct maxpCtx_)); /* Link contexts */ h->g = g; g->ctx.maxp = h; }
void postNew(hotCtx g) { postCtx h = MEM_NEW(g, sizeof(struct postCtx_)); /* Link contexts */ h->g = g; g->ctx.post = h; }
void vmtxNew(hotCtx g) { vmtxCtx h = MEM_NEW(g, sizeof(struct vmtxCtx_)); dnaINIT(g->dnaCtx, h->tbl.vMetrics, 14000, 14000); dnaINIT(g->dnaCtx, h->tbl.topSideBearing, 14000, 14000); /* Link contexts */ h->g = g; g->ctx.vmtx = h; }
void hheaNew(hotCtx g) { hheaCtx h = MEM_NEW(g, sizeof(struct hheaCtx_)); h->tbl.caretOffset = SHRT_MAX; /* Link contexts */ h->g = g; g->ctx.hhea = h; }
void anonNew(hotCtx g) { anonCtx h = MEM_NEW(g, sizeof(struct anonCtx_)); dnaINIT(g->dnaCtx, h->tbls, 5, 5); h->iTbl = 0; /* Link contexts */ h->g = g; g->ctx.anon = h; }
/* * saves the current top of the text space * * TODO: * - text_save() and text_restore() can be improved to detect erroneous calls as shown in the * above example; * - the stack-like storage management by text_save() and text_restore() unnecessarily keeps the * library from being used in ohter libraries. For example, text_restore() invoked by a * clean-up function of a library can destroy the storage for texts that are still in use by a * program. The approach used by the arena library would be more appropriate. * * The original code calls alloc() to keep a text from straddling the end of the text space that * is returned by text_save(). This seems unnecessary in this implementation, so commented out. */ text_save_t *(text_save)(void) { text_save_t *save; MEM_NEW(save); save->current = current; save->avail = current->avail; /* alloc(1); */ return save; }
/* Initialize module */ void encodingNew(tcCtx g) { encodingCtx h = MEM_NEW(g, sizeof(struct encodingCtx_)); dnaINIT(g->ctx.dnaCtx, h->encodings, 1, 10); h->encodings.func = initEncoding; /* Link contexts */ h->g = g; g->ctx.encoding = h; }
void MMSDNew(hotCtx g) { MMSDCtx h = MEM_NEW(g, sizeof(struct MMSDCtx_)); h->tbl.axis_.axis_ = NULL; h->tbl.instance_.instance_ = NULL; h->tbl.style_.style_ = NULL; /* Link contexts */ h->g = g; g->ctx.MMSD = h; }
void MMFXNew(hotCtx g) { MMFXCtx h = MEM_NEW(g, sizeof(struct MMFXCtx_)); h->nextUnnamedId = MMFXNamedMetricCnt; h->tbl.offset = NULL; dnaINIT(g->dnaCtx, h->metrics, 1000, 2000); dnaINIT(g->dnaCtx, h->cstrs, 5000, 10000); /* Link contexts */ h->g = g; g->ctx.MMFX = h; }
/* Add encoding to accumulator if unique and return index */ int encodingAdd(tcCtx g, int nCodes, unsigned char *code, int nSups, CodeMap *supplement) { encodingCtx h = g->ctx.encoding; int i; Encoding *encoding; for (i = 0; i < h->encodings.cnt; i++) { encoding = &h->encodings.array[i]; if (nCodes == encoding->nCodes && nSups == encoding->nSups) { int j; for (j = 0; j < nCodes; j++) if (code[j] != encoding->code[j]) goto mismatch; for (j = 0; j < nSups; j++) if (supplement[j].code != encoding->supplement[j].code || supplement[j].sid != encoding->supplement[j].sid) goto mismatch; return PREDEF_CNT + i; /* Found match */ mismatch: ; } } /* No match found; add encoding */ encoding = dnaNEXT(h->encodings); encoding->nCodes = nCodes; encoding->code = MEM_NEW(g, nCodes); COPY(encoding->code, code, nCodes); encoding->nSups = nSups; if (nSups > 0) { encoding->supplement = MEM_NEW(g, nSups * sizeof(CodeMap)); COPY(encoding->supplement, supplement, nSups); } return PREDEF_CNT + h->encodings.cnt - 1; }
/* Create new context */ tcCtx tcNew(tcCallbacks *cb) { tcCtx g = cb->malloc(cb->ctx, sizeof(struct tcCtx_)); tcprivCtx h; g->cb = *cb; h = MEM_NEW(g, sizeof(struct tcprivCtx_)); tc_dna_memcb.ctx = g; tc_dna_memcb.manage = tc_manage; g->ctx.dnaCtx = dnaNew(&tc_dna_memcb, DNA_CHECK_ARGS); dnaINIT(g->ctx.dnaCtx, h->set, 4, 120); h->set.func = fontInit; initSet(g, h); /* Initialize other library modules */ g->ctx.sindex = NULL; g->ctx.fdselect = NULL; g->ctx.subr = NULL; g->ctx.cs = NULL; g->ctx.encoding = NULL; g->ctx.charset = NULL; g->ctx.recode = NULL; g->ctx.parse = NULL; g->ctx.tcpriv = NULL; g->ctx.t13 = NULL; sindexNew(g); encodingNew(g); charsetNew(g); parseNew(g); csNew(g); recodeNew(g); #if TC_SUBR_SUPPORT subrNew(g); #endif /* TC_SUBR_SUPPORT */ fdselectNew(g); t13New(g); /* Link contexts */ h->g = g; g->ctx.tcpriv = h; return g; }
/* * constructs a default set for configuration variables * * conf_preset() cannot be implemented with conf_set() since they differ in handling an omitted * section name. conf_section() cannot affect conf_preset() because the former is not callable * before the latter. Thus, conf_preset() can safely assume that a section name is given properly * whenever necessary. On the other hand, because conf_set() is affected by conf_section(), a * variable name without a section name and a period should be recognized as referring to the * current section, not to the global section. * * TODO: * - some adjustment on arguments to table_new() is necessary; * - considering changes to the format of a configuration file as a program to accept it is * upgraded, making it a recoverable error to encounter a non-preset section or variable name * would be useful; this enables an old version of the program to accept a new configuration * file with diagnostics. */ int (conf_preset)(const conf_t *tab, int ctrl) { size_t len; char *pbuf, *sec, *var; const char *hkey; table_t *t; struct valnode_t *pnode; assert(!section); assert(tab); control = ctrl; section = table_new(0, NULL, NULL); errcode = CONF_ERR_OK; for (; tab->var; tab++) { assert(tab->defval); assert(tab->type == CONF_TYPE_BOOL || tab->type == CONF_TYPE_INT || tab->type == CONF_TYPE_UINT || tab->type == CONF_TYPE_REAL || tab->type == CONF_TYPE_STR); len = strlen(tab->var); pbuf = strcpy(MEM_ALLOC(len+1 + strlen(tab->defval)+1), tab->var); if (sep(pbuf, &sec, &var) != CONF_ERR_OK) { MEM_FREE(pbuf); break; /* sep sets errcode */ } if (!sec) /* means global section in this case */ sec = ""; /* lower modifies sec only when necessary */ hkey = hash_string((control & CONF_OPT_CASE)? sec: lower(sec)); t = table_get(section, hkey); if (!t) { /* new section */ t = table_new(0, NULL, NULL); table_put(section, hkey, t); } MEM_NEW(pnode); pnode->type = tab->type; pnode->freep = pbuf; pnode->val = strcpy(pbuf + len+1, tab->defval); table_put(t, hash_string((control & CONF_OPT_CASE)? var: lower(var)), pnode); } preset = 1; return errcode; }
void CDatabase::AddElement(const char *pType, const char *pModelName, CParameters *paParameters) { const CElementModel *pModel = m_pModelsDatabase->FindElementModel(pType, pModelName); if(!pModel) { printf("error: couldn't find model '%s' of type '%s'\n", pModelName, pType); PrintCallstack(); return; } CElement *pElement = MEM_NEW(CElement(this, pModel, m_ElementsCount++, paParameters)); CElementsGroup *pGroup = GetElementsGroup(pType); pGroup->m_apList.Add(pElement); pElement->CallFunction("$on_add", paParameters); #ifdef SPB_DEBUG printf("success: added element %p (type '%s', model '%s')\n", pElement, pType, pModelName); #endif }
int MMFXFill(hotCtx g) { MMFXCtx h = g->ctx.MMFX; int i; Offset offset; if (!IS_MM(g)) { return 0; } /* Fill header */ h->tbl.version = VERSION(1, 0); h->tbl.nMetrics = (unsigned short)h->metrics.cnt; h->tbl.offSize = (HEADER_SIZE + uint16 * h->metrics.cnt + h->metrics.array[h->metrics.cnt - 1].index > 65535) ? 4 : 2; /* Sort metrics by id */ qsort(h->metrics.array, h->metrics.cnt, sizeof(Metric), cmpIds); /* Check if all named metrics present */ for (i = 0; i < h->metrics.cnt; i++) { if (h->metrics.array[i].id >= MMFXNamedMetricCnt) { break; } } if (i < MMFXNamedMetricCnt) { hotMsg(g, hotFATAL, "Missing named metrics"); } else if (i > MMFXNamedMetricCnt) { hotMsg(g, hotFATAL, "Duplicate named metrics"); } /* Allocate and fill offset array */ offset = (unsigned short)(HEADER_SIZE + h->tbl.offSize * h->metrics.cnt); h->tbl.offset = MEM_NEW(g, sizeof(long) * h->metrics.cnt); for (i = 0; i < h->metrics.cnt; i++) { h->tbl.offset[i] = offset + h->metrics.array[i].index; } return 1; }
int SYNTH_HANDLER( PSYTEXX_SYNTH_PARAMETERS ) { psynth_net *pnet = (psynth_net*)net; SYNTH_DATA *data = (SYNTH_DATA*)data_ptr; int retval = 0; int i; switch( command ) { case COMMAND_GET_DATA_SIZE: retval = sizeof( SYNTH_DATA ); break; case COMMAND_GET_SYNTH_NAME: retval = (int)"Reverb"; break; case COMMAND_GET_SYNTH_INFO: retval = (int)"Reverb + DC Blocking Filter.\n(Based on FreeVerb)"; break; case COMMAND_GET_INPUTS_NUM: retval = SYNTH_INPUTS; break; case COMMAND_GET_OUTPUTS_NUM: retval = SYNTH_OUTPUTS; break; case COMMAND_GET_FLAGS: retval = PSYNTH_FLAG_EFFECT; break; case COMMAND_INIT: psynth_register_ctl( synth_id, "Dry", "", 0, 256, 256, 0, &data->ctl_dry, net ); psynth_register_ctl( synth_id, "Wet", "", 0, 256, 64, 0, &data->ctl_wet, net ); psynth_register_ctl( synth_id, "Feedback", "", 0, 256, 256, 0, &data->ctl_feedback, net ); psynth_register_ctl( synth_id, "Damp", "", 0, 256, 128, 0, &data->ctl_damp, net ); psynth_register_ctl( synth_id, "Width", "", 0, 256, 256, 0, &data->ctl_width, net ); psynth_register_ctl( synth_id, "Freeze", "", 0, 1, 0, 1, &data->ctl_freeze, net ); psynth_register_ctl( synth_id, "Mode", "HQ/HQmono/LQ/LQmono", 0, MODES - 1, MODE_HQ, 1, &data->ctl_mode, net ); //Init comb filters: data->combs_num = MAX_COMBS; for( i = 0; i < data->combs_num * 2; i++ ) { data->combs[ i ].buf = (STYPE_CALC*)MEM_NEW( HEAP_DYNAMIC, MAX_COMB_BUF_SIZE * sizeof( STYPE_CALC ) ); data->combs[ i ].buf_ptr = 0; data->combs[ i ].filterstore = 0; } i = 0; data->combs[ i ].buf_size = 1116; data->combs[ i + MAX_COMBS ].buf_size = data->combs[ i ].buf_size + STEREO_SPREAD; i++; data->combs[ i ].buf_size = 1188; data->combs[ i + MAX_COMBS ].buf_size = data->combs[ i ].buf_size + STEREO_SPREAD; i++; data->combs[ i ].buf_size = 1277; data->combs[ i + MAX_COMBS ].buf_size = data->combs[ i ].buf_size + STEREO_SPREAD; i++; data->combs[ i ].buf_size = 1356; data->combs[ i + MAX_COMBS ].buf_size = data->combs[ i ].buf_size + STEREO_SPREAD; i++; data->combs[ i ].buf_size = 1422; data->combs[ i + MAX_COMBS ].buf_size = data->combs[ i ].buf_size + STEREO_SPREAD; i++; data->combs[ i ].buf_size = 1491; data->combs[ i + MAX_COMBS ].buf_size = data->combs[ i ].buf_size + STEREO_SPREAD; i++; data->combs[ i ].buf_size = 1557; data->combs[ i + MAX_COMBS ].buf_size = data->combs[ i ].buf_size + STEREO_SPREAD; i++; data->combs[ i ].buf_size = 1617; data->combs[ i + MAX_COMBS ].buf_size = data->combs[ i ].buf_size + STEREO_SPREAD; i++; //Init allpass filters: data->allpasses_num = MAX_ALLPASSES; for( i = 0; i < data->allpasses_num * 2; i++ ) { data->allpasses[ i ].buf = (STYPE_CALC*)MEM_NEW( HEAP_DYNAMIC, MAX_ALLPASS_BUF_SIZE * sizeof( STYPE_CALC ) ); data->allpasses[ i ].buf_ptr = 0; #ifdef STYPE_FLOATINGPOINT data->allpasses[ i ].feedback = (STYPE_CALC)0.5; #else data->allpasses[ i ].feedback = 128; #endif } i = 0; data->allpasses[ i ].buf_size = 556; data->allpasses[ i + MAX_ALLPASSES ].buf_size = data->allpasses[ i ].buf_size + STEREO_SPREAD; i++; data->allpasses[ i ].buf_size = 441; data->allpasses[ i + MAX_ALLPASSES ].buf_size = data->allpasses[ i ].buf_size + STEREO_SPREAD; i++; data->allpasses[ i ].buf_size = 341; data->allpasses[ i + MAX_ALLPASSES ].buf_size = data->allpasses[ i ].buf_size + STEREO_SPREAD; i++; data->allpasses[ i ].buf_size = 225; data->allpasses[ i + MAX_ALLPASSES ].buf_size = data->allpasses[ i ].buf_size + STEREO_SPREAD; i++; //Fix buffer sizes: if( pnet->sampling_freq != 44100 ) { int delta = ( pnet->sampling_freq << 11 ) / 44100; for( int i = 0; i < data->combs_num * 2; i++ ) data->combs[ i ].buf_size = ( data->combs[ i ].buf_size * delta ) >> 11; for( int i = 0; i < data->allpasses_num * 2; i++ ) data->allpasses[ i ].buf_size = ( data->allpasses[ i ].buf_size * delta ) >> 11; } clean_filters( data ); //DC Offset removing filter: { float dc_block_freq = 5.0F; float dc_block_pole = ( (2*3.1415926535F) * dc_block_freq ) / (float)pnet->sampling_freq; #ifdef STYPE_FLOATINGPOINT data->dc_block_pole = (STYPE_CALC)1.0 - dc_block_pole; #else data->dc_block_pole = (STYPE_CALC)( 32768.0F * dc_block_pole ); #endif } data->dc_block_acc_L = 0; data->dc_block_prev_x_L = 0; data->dc_block_prev_y_L = 0; data->dc_block_acc_R = 0; data->dc_block_prev_x_R = 0; data->dc_block_prev_y_R = 0; data->filters_reinit_request = 1; retval = 1; break; case COMMAND_CLEAN: clean_filters( data ); data->dc_block_acc_L = 0; data->dc_block_prev_x_L = 0; data->dc_block_prev_y_L = 0; data->dc_block_acc_R = 0; data->dc_block_prev_x_R = 0; data->dc_block_prev_y_R = 0; retval = 1; break; case COMMAND_RENDER_REPLACE: if( !inputs[ 0 ] || !outputs[ 0 ] ) break; if( data->ctl_mode == MODE_HQ_MONO || data->ctl_mode == MODE_LQ_MONO ) psynth_set_number_of_outputs( 1, synth_id, pnet ); else psynth_set_number_of_outputs( SYNTH_OUTPUTS, synth_id, pnet ); { STYPE *inL_ch = inputs[ 0 ]; STYPE *inR_ch = inputs[ 1 ]; STYPE *outL_ch = outputs[ 0 ]; STYPE *outR_ch = outputs[ 1 ]; int outputs_num = psynth_get_number_of_outputs( synth_id, pnet ); if( outputs_num == 1 ) { inR_ch = 0; outR_ch = 0; } else { outputs_num = 2; //Stereo } int filters_add; if( data->ctl_mode < MODE_LQ ) filters_add = 1; else filters_add = 2; //Skip every second filter //Reinit filters: if( data->filters_reinit_request ) { reinit_filter_parameters( data, pnet ); data->filters_reinit_request = 0; } int ctl_dry = data->ctl_dry; int ctl_wet = data->ctl_wet; if( filters_add > 1 ) ctl_wet *= 2; for( int ch = 0; ch < outputs_num; ch++ ) { STYPE *in = inputs[ ch ]; STYPE *out = outputs[ ch ]; STYPE_CALC dc_block_pole; STYPE_CALC dc_block_acc; STYPE_CALC dc_block_prev_x; STYPE_CALC dc_block_prev_y; dc_block_pole = data->dc_block_pole; if( ch == 0 ) { dc_block_acc = data->dc_block_acc_L; dc_block_prev_x = data->dc_block_prev_x_L; dc_block_prev_y = data->dc_block_prev_y_L; } else { dc_block_acc = data->dc_block_acc_R; dc_block_prev_x = data->dc_block_prev_x_R; dc_block_prev_y = data->dc_block_prev_y_R; } for( int i = 0; i < sample_frames; i++ ) { STYPE_CALC input = in[ i ]; #ifdef STYPE_FLOATINGPOINT //Floating-Point DC Blocking Filter: dc_block_prev_y = input - dc_block_prev_x + dc_block_prev_y * dc_block_pole; dc_block_prev_x = input; input = dc_block_prev_y; denorm_add_white_noise( input ); #else //Fixed-Point DC Blocking Filter With Noise-Shaping: dc_block_acc -= dc_block_prev_x; dc_block_prev_x = input << 15; dc_block_acc += dc_block_prev_x; dc_block_acc -= dc_block_pole * dc_block_prev_y; dc_block_prev_y = dc_block_acc >> 15; // quantization happens here input = dc_block_prev_y; #endif out[ i ] = (STYPE)input; } if( ch == 0 ) { data->dc_block_acc_L = dc_block_acc; data->dc_block_prev_x_L = dc_block_prev_x; data->dc_block_prev_y_L = dc_block_prev_y; } else { data->dc_block_acc_R = dc_block_acc; data->dc_block_prev_x_R = dc_block_prev_x; data->dc_block_prev_y_R = dc_block_prev_y; } } for( int i = 0; i < sample_frames; i++ ) { //Output signals: STYPE_CALC outL = 0; STYPE_CALC outR = 0; //Input signals: STYPE_CALC input; if( inR_ch ) { input = ( outL_ch[ i ] + outR_ch[ i ] ) / 2; } else { input = outL_ch[ i ]; } input *= INPUT_MUL; //decrease noise in fixed point mode //Accumulate comb filters in parallel: for( int a = 0; a < data->combs_num * outputs_num; a += filters_add ) { comb_filter *f = &data->combs[ a ]; STYPE_CALC f_out = f->buf[ f->buf_ptr ]; #ifdef STYPE_FLOATINGPOINT f->filterstore = ( f_out * f->damp1 ) + ( f->filterstore * f->damp2 ); //f->filterstore = undenormalize( f->filterstore ); //f->buf[ f->buf_ptr ] = undenormalize( input + ( f->filterstore * f->feedback ) ); f->buf[ f->buf_ptr ] = input + ( f->filterstore * f->feedback ); #else STYPE_CALC f_v; f->filterstore = ( f_out * f->damp1 + f->filterstore * f->damp2 ) / 256; f_v = input + ( f->filterstore * f->feedback ) / 256; f->buf[ f->buf_ptr ] = f_v; #endif if( a < MAX_COMBS ) outL += f_out; else outR += f_out; if( ++f->buf_ptr >= f->buf_size ) f->buf_ptr = 0; } //Feed through allpasses in series: for( int a = 0; a < data->allpasses_num * outputs_num; a += filters_add ) { allpass_filter *f = &data->allpasses[ a ]; STYPE_CALC f_bufout = f->buf[ f->buf_ptr ]; STYPE_CALC f_out; STYPE_CALC f_in; //f_bufout = undenormalize( f_bufout ); if( a < MAX_ALLPASSES ) f_in = outL; else f_in = outR; f_out = -f_in + f_bufout; #ifdef STYPE_FLOATINGPOINT f->buf[ f->buf_ptr ] = f_in + ( f_bufout * f->feedback ); #else STYPE_CALC f_v; f_v = f_in + ( f_bufout * f->feedback ) / 256; f->buf[ f->buf_ptr ] = f_v; #endif if( a < MAX_ALLPASSES ) outL = f_out; else outR = f_out; if( ++f->buf_ptr >= f->buf_size ) f->buf_ptr = 0; } outL_ch[ i ] = (STYPE)( (STYPE_CALC)( ( outL / (16*INPUT_MUL) ) * ctl_wet ) / 256 ); outL_ch[ i ] += (STYPE)( (STYPE_CALC)( inL_ch[ i ] * ctl_dry ) / 256 ); if( inR_ch ) { outR_ch[ i ] = (STYPE)( (STYPE_CALC)( ( outR / (16*INPUT_MUL) ) * ctl_wet ) / 256 ); outR_ch[ i ] += (STYPE)( (STYPE_CALC)( inR_ch[ i ] * ctl_dry ) / 256 ); } } if( outputs_num == 2 && data->ctl_width < 256 ) { int ctl_width = data->ctl_width / 2 + 128; int ctl_width2 = 256 - ctl_width; for( int i = 0; i < sample_frames; i++ ) { STYPE_CALC outL; STYPE_CALC outR; outL = ( (STYPE_CALC)outL_ch[ i ] * ctl_width ) / 256 + ( (STYPE_CALC)outR_ch[ i ] * ctl_width2 ) / 256; outR = ( (STYPE_CALC)outR_ch[ i ] * ctl_width ) / 256 + ( (STYPE_CALC)outL_ch[ i ] * ctl_width2 ) / 256; outL_ch[ i ] = outL; outR_ch[ i ] = outR; } } } retval = 1; break; case COMMAND_SET_GLOBAL_CONTROLLER: case COMMAND_SET_LOCAL_CONTROLLER: data->filters_reinit_request = 1; break; case COMMAND_CLOSE: for( i = 0; i < data->combs_num * 2; i++ ) { mem_free( data->combs[ i ].buf ); } for( i = 0; i < data->allpasses_num * 2; i++ ) { mem_free( data->allpasses[ i ].buf ); } retval = 1; break; }
/* * reads a configuration file and constructs the configuration data * * A tricky construct using do-while for reading lines from a file is to allow for a configuration * file that does not end with a newline. Asserting that BUFLEN is greater than 1 is necessary to * prevent fgets() from returning an empty string even if there are still characters unread. * TODO: * - some adjustment on arguments to table_new() is necessary */ size_t (conf_init)(FILE *fp, int ctrl) { char *p; size_t buflen, len; size_t lineno, nlineno; const char *hkey; table_t *tab; struct valnode_t *pnode; assert(fp); assert(preset || !section); assert(!current); assert(BUFLEN > 1); if (!preset) { control = ctrl; /* if preset, ctrl ignored */ section = table_new(0, NULL, NULL); } tab = NULL; errcode = CONF_ERR_OK; lineno = nlineno = 0; len = 0; p = MEM_ALLOC(buflen=BUFLEN); *p = '\0'; do { assert(buflen - len > 1); fgets(p+len, buflen-len, fp); if (ferror(fp)) { errcode = CONF_ERR_IO; break; } len += strlen(p+len); if (len == 0) /* EOF and no remaining data */ break; if (len > 2 && p[len-2] == '\\' && p[len-1] == '\n') { /* line splicing */ int c; nlineno++; len -= 2; if (len > 0 && isspace(p[len-1])) { while (--len > 0 && isspace(p[len-1])) continue; p[len++] = ' '; } if ((c = getc(fp)) != EOF && c != '\n' && isspace(c)) { if (p[len-1] != ' ') p[len++] = ' '; while ((c = getc(fp)) != EOF && c != '\n' && isspace(c)) continue; } else if (c == EOF) { /* no following line for slicing */ lineno += nlineno; errcode = CONF_ERR_BSLASH; goto retcode; } ungetc(c, fp); p[len] = '\0'; /* at worst, backslash is replaced with space and newline with null, thus room for two characters, which guarantees buflen-len greater than 1 */ } else if (p[len-1] == '\n' || feof(fp)) { /* line completed */ int type; char *s, *t, *var, *val; lineno++; if (p[len-1] == '\n') p[--len] = '\0'; /* in fact, no need to adjust len */ var = triml(p); switch(*var) { case '[': /* section specification */ cmtrem(++var); s = strchr(var, ']'); if (!s) { errcode = CONF_ERR_LINE; goto retcode; } *s = '\0'; if (sepunit(var, &var) != CONF_ERR_OK) goto retcode; /* sepunit sets errcode */ hkey = hash_string((control & CONF_OPT_CASE)? var: lower(var)); tab = table_get(section, hkey); if (!tab) { if (preset) { errcode = CONF_ERR_SEC; goto retcode; } tab = table_new(0, NULL, NULL); } table_put(section, hkey, tab); /* no break */ case '\0': /* empty line */ case '#': /* comment-only line */ case ';': break; /* reuses existing buffer */ default: /* variable = value */ val = p + strcspn(p, "#;"); s = strchr(var, '='); if (!s || val < s) { errcode = CONF_ERR_LINE; goto retcode; } *s = '\0'; if (sepunit(var, &var) != CONF_ERR_OK) goto retcode; /* sepunit() sets errcode */ if (*(unsigned char *)var == '\0') { /* empty variable name */ errcode = CONF_ERR_VAR; goto retcode; } val = triml(++s); if (*val == '"' || *val == '\'') { /* quoted */ char end = *val; /* remembers for match */ t = s = ++val; /* starts copying from s to t */ do { switch(*s) { case '\\': /* escape sequence */ if (control & CONF_OPT_ESC) *(unsigned char *)t++ = escseq(*(unsigned char *)++s); else { *t++ = '\\'; *(unsigned char *)t++ = *(unsigned char *)++s; } break; case '\0': /* unclosed ' or " */ errcode = CONF_ERR_LINE; goto retcode; case '\'': case '\"': if (*s == end) { *t = '\0'; break; } /* no break */ default: /* literal copy */ *(unsigned char *)t++ = *(unsigned char *)s; break; } s++; } while(*(unsigned char *)t != '\0'); /* checks if any trailing invalid char */ cmtrem(s); trimt(s); if (*(unsigned char *)s != '\0') { errcode = CONF_ERR_LINE; goto retcode; } } else { /* unquoted */ cmtrem(val); trimt(val); } if (!tab) { /* global section */ hkey = hash_string(""); tab = table_get(section, hkey); if (!tab) { if (preset) { errcode = CONF_ERR_SEC; goto retcode; } tab = table_new(0, NULL, NULL); } table_put(section, hkey, tab); } hkey = hash_string((control & CONF_OPT_CASE)? var: lower(var)); if (preset) { pnode = table_get(tab, hkey); if (!pnode) { errcode = CONF_ERR_VAR; goto retcode; } type = pnode->type; } else type = CONF_TYPE_STR; MEM_NEW(pnode); pnode->freep = p; pnode->type = type; pnode->val = val; pnode = table_put(tab, hkey, pnode); if (pnode) { /* value overwritten, thus free */ MEM_FREE(pnode->freep); MEM_FREE(pnode); } p = MEM_ALLOC(buflen=BUFLEN); /* uses new buffer */ break; } len = 0; *p = '\0'; lineno += nlineno; /* adjusts line number */ nlineno = 0; } else /* expands buffer */ MEM_RESIZE(p, buflen+=BUFLEN); } while(!feof(fp)); retcode: MEM_FREE(p); return (errcode != CONF_ERR_OK)? lineno: 0; }
int MMSDFill(hotCtx g) { int i; Offset offset; MMSDCtx h = g->ctx.MMSD; if (!IS_MM(g)) { return 0; } h->tbl.version = VERSION(1, 0); h->tbl.flags = 0; if (g->font.flags & HOT_USE_FOR_SUBST) { h->tbl.flags |= MMSD_USE_FOR_SUBST; } if (g->font.flags & HOT_CANT_INSTANCE) { h->tbl.flags |= MMSD_CANT_INSTANCE; } /* Fill axis table */ h->tbl.axis_.nAxes = (unsigned short)g->font.mm.axis.cnt; h->tbl.axis_.axisSize = AXIS_SIZE; h->tbl.axis_.axis_ = MEM_NEW(g, sizeof(AxisRec) * h->tbl.axis_.nAxes); for (i = 0; i < h->tbl.axis_.nAxes; i++) { AxisRec *dst = &h->tbl.axis_.axis_[i]; MMAxis *src = &g->font.mm.axis.array[i]; dst->longLabel_ = src->longLabel; dst->shortLabel_ = src->shortLabel; } if (g->font.mm.instance.cnt != 0) { /* Fill instance table */ h->tbl.instance_.nInstances = (unsigned short)g->font.mm.instance.cnt; h->tbl.instance_.instanceSize = INSTANCE_SIZE; h->tbl.instance_.instance_ = MEM_NEW(g, sizeof(InstanceRec) * h->tbl.instance_.nInstances); for (i = 0; i < h->tbl.instance_.nInstances; i++) { h->tbl.instance_.instance_[i].nameSuffix_ = g->font.mm.instance.array[i].suffix; } } else { h->tbl.instance_.nInstances = 0; } if (g->font.mm.style.cnt != 0) { /* Fill style table */ h->tbl.style_.nStyles = (unsigned short)g->font.mm.style.cnt; h->tbl.style_.styleSize = STYLE_SIZE; h->tbl.style_.style_ = MEM_NEW(g, sizeof(StyleRec) * h->tbl.style_.nStyles); for (i = 0; i < h->tbl.style_.nStyles; i++) { StyleRec *dst = &h->tbl.style_.style_[i]; MMStyle *src = &g->font.mm.style.array[i]; dst->axis = (unsigned char)src->axis; dst->flags = (unsigned char)src->flags; dst->action[0].point = src->action[0].point; dst->action[0].delta = src->action[0].delta; dst->action[1].point = src->action[1].point; dst->action[1].delta = src->action[1].delta; } } else { h->tbl.style_.nStyles = 0; } /* Fill offsets */ h->tbl.axis = offset = HEADER_SIZE; offset += AXIS_TBL_SIZE(h); if (h->tbl.instance_.nInstances != 0) { h->tbl.instance = offset; offset += INSTANCE_TBL_SIZE(h); } else { h->tbl.instance = 0; } if (h->tbl.style_.nStyles != 0) { h->tbl.style = offset; offset += STYLE_TBL_SIZE(h); } else { h->tbl.style = 0; } /* Calculate string offsets */ for (i = 0; i < h->tbl.axis_.nAxes; i++) { AxisRec *axis = &h->tbl.axis_.axis_[i]; axis->longLabel = offset; offset += strlen(axis->longLabel_) + 1; axis->shortLabel = offset; offset += strlen(axis->shortLabel_) + 1; } if (h->tbl.instance != 0) { for (i = 0; i < h->tbl.instance_.nInstances; i++) { InstanceRec *instance = &h->tbl.instance_.instance_[i]; instance->nameSuffix = offset; offset += strlen(instance->nameSuffix_) + 1; } } return 1; }
/* * inserts or replaces a value associated with a variable * * TODO: * - some adjustment on arguments to table_new() is necessary */ int (conf_set)(const char *secvar, const char *value) { size_t len; char buf[30], *pbuf; char *sec, *var; table_t *tab; const char *hkey; struct valnode_t *pnode; assert(secvar); assert(value); /* sep() always clears errcode */ len = strlen(secvar); pbuf = strcpy((len > sizeof(buf)-1)? MEM_ALLOC(len+1): buf, secvar); if (sep(pbuf, &sec, &var) != CONF_ERR_OK) { if (pbuf != buf) MEM_FREE(pbuf); return errcode; /* sep sets errcode */ } if (!sec) { /* current selected */ if (!current) { /* no current section, thus global */ hkey = hash_string(""); /* in case table for global not yet allocated */ tab = table_get(section, hkey); } else tab = current; } else { /* section name given */ hkey = hash_string((control & CONF_OPT_CASE)? sec: lower(sec)); tab = table_get(section, hkey); } if (!tab) { /* new section */ if (preset) { if (pbuf != buf) MEM_FREE(pbuf); return (errcode = CONF_ERR_SEC); } else { /* adds it */ tab = table_new(0, NULL, NULL); table_put(section, hkey, tab); } } assert(tab); hkey = hash_string((control & CONF_OPT_CASE)? var: lower(var)); if (pbuf != buf) MEM_FREE(pbuf); pnode = table_get(tab, hkey); if (!pnode) { /* new variable */ if (preset) return (errcode = CONF_ERR_VAR); else { /* inserts */ MEM_NEW(pnode); pnode->type = CONF_TYPE_STR; table_put(tab, hkey, pnode); } } else /* replaces, thus reuses pnode */ MEM_FREE(pnode->freep); pnode->val = pnode->freep = strcpy(MEM_ALLOC(strlen(value)+1), value); return errcode; }