/* return non-negative on success; -1 on error; non-negative is the length of string parsed by f2_parse. */ int f2_parse(const Uchar *file, size_t line, Uchar *lp, struct f2 *f2p, Uchar **psu_sense, struct sig_context *scp) { Uchar *tmp = NULL, *err_lp = NULL, *disambig = NULL, *ampamp = NULL, *orig_lp = lp, field = '\0', *psu_tmp = NULL; int ret = 0; const char *saved_phase = phase; int square, saved_with_textid = with_textid; if (!lp) return 1; /* err_lp = npool_copy(lp, scp->pool); */ err_lp = (Uchar*)strdup((char*)lp); phase = "f2"; with_textid = 0; /* skip the old shadow lem codes */ if (*lp == '`') { vwarning2((char*)file,line,"%s: please remove deprecated shadow lem sequence '`' or '`?'",err_lp); lp += 1 + (lp[1] == '?'); } if ((ampamp = (unsigned char*)strstr((char*)lp, "&&"))) { f2_parse_cof(file, line, lp, f2p, psu_sense, ampamp, scp); goto ret; } /* if the sig starts with @ parse the admin fields @PROJ%LANG:FORM= * first. * * N.B.: % and : are not recognized by field_end() as this causes * problems parsing morphology. */ if ('@' == *lp) { f2p->project = lp+1; lp = (Uchar*)strchr((char*)lp,'%'); if (lp) { *lp++ = '\0'; f2p->lang = lp; f2p->core = langcore_of((const char*)lp); lp = (Uchar*)strchr((char*)lp,':'); if (lp) { *lp++ = '\0'; f2p->form = lp; lp = (Uchar*)strchr((char*)lp,'='); *lp++ = '\0'; } } } if ('[' == *lp) { /* FIXME: this needs to be more rigorous and check for CF-legal char in initial position */ vwarning2((char*)file,line,"%s: lemmatization cannot begin with '['",err_lp); goto ret; } if (!strchr((const char *)lp,'[')) { /* f2p->cf = "X"; */ f2p->gw = (unsigned char *)"X"; if (*lp == 'n') { f2p->pos = "n"; ++lp; } else if (*lp == 'u') { f2p->pos = "u"; ++lp; } goto pos_parse; } /* parse the CF[GW/SENSE]POS'EPOS which are constant: */ f2p->cf = lp; if (*lp == '"') { ++lp; f2p->cf = lp; /* don't include quotes in the CF; WATCHME: what happens in post-cache retrieval parse? */ BIT_SET(f2p->flags,F2_FLAGS_CF_QUOTED); /* fp->explicit |= NEW_CF; */ /* have to do something here, i.e., suppress charset translation */ } while (*lp && (*lp != '[' || lp[-1] == '\\')) ++lp; if (BIT_ISSET(f2p->flags,F2_FLAGS_CF_QUOTED)) { if (lp[-1] == '"') lp[-1] = '\0'; else { vwarning2((char*)file,line,"%s: '\"' missing on quoted CF",err_lp); ret = -1; } } if (lp) *lp = '\0'; else goto ret; if (lp[-1] == ')' && lp[-2] != '\\') { char *oparen = strchr((char*)f2p->cf,'('); if (oparen && oparen[-1] != '\\') { *oparen++ = '\0'; f2p->restrictor = (unsigned char*)oparen; lp[-1] = '\0'; } else { vwarning2((char*)file,line,"%s: '(' missing on restrictor",err_lp); ret = -1; goto ret; } } else if ((tmp = (unsigned char*)strchr((char*)f2p->cf,'(')) && tmp[-1] != '\\') { vwarning2((char*)file,line,"%s: ')' missing on restrictor",err_lp); ret = -1; goto ret; } f2p->gw = ++lp; if ((psu_tmp = (Uchar *)strstr(cc(lp),"+="))) { *psu_tmp = '\0'; psu_tmp += 2; if (psu_sense) *psu_sense = psu_tmp; psu_tmp = (Uchar *)strchr((const char *)psu_tmp,']'); } /* make SENSE optional here to support inline lem parsing */ square = 0; while (*lp && (*lp != '/' || lp[1] != '/')) { if (*lp == '[' && lp[-1] != '\\') ++square; else if (*lp == ']' && lp[-1] != '\\') { if (square) --square; else break; } ++lp; } /* If we didn't find ] but had a psu_sense with +=, reset lp to the closing square bracket after the psu_sense */ if (!*lp && psu_tmp) lp = psu_tmp; if (*lp) { if ('/' == *lp) { *lp++ = '\0'; ++lp; f2p->sense = lp; square = 0; while (*lp) { if (*lp == '[' && lp[-1] != '\\') ++square; else if (*lp == ']' && lp[-1] != '\\') { if (square) --square; else break; } ++lp; } } if (*lp) /* lp is at closing square bracket of CF[GW] */ { *lp++ = '\0'; /* This is either a POS or something that starts with a field char */ pos_parse: if (isupper(*lp)) { Uchar *end = NULL; Uchar *epos = NULL; for (end = lp; *end && !isspace(*end); ++end) ; epos = (Uchar*)strchr((const char *)lp,'\''); f2p->pos = lp; if (epos && epos < end) lp = epos; else lp = field_end(lp); if (*f2p->pos == 'V' && '/' == *lp && (lp[1] == 't' || lp[1] == 'i')) { ++lp; epos = (Uchar*)strchr((const char *)lp,'\''); if (epos && epos < end) lp = epos; else lp = field_end(lp); } field = *lp; if (field == '\'') { *lp++ = '\0'; f2p->epos = lp; lp = field_end(lp); if (*f2p->epos == 'V' && '/' == *lp && (lp[1] == 't' || lp[1] == 'i')) { ++lp; lp = field_end(lp); } field = *lp; *lp++ = '\0'; } else *lp++ = '\0'; } else if (*lp == '\'') { *lp++ = '\0'; f2p->epos = lp; lp = field_end(lp); field = *lp; *lp++ = '\0'; } else if (*lp) { field = *lp; *lp++ = '\0'; } /* Now we are at a variable set of instance fields; parse as though they can be in any order, though in principle the order should always be fixed. */ while (*lp) { switch (field) { #if 0 /* this must follow POS and ' is no longer a field * ender because of conflict with ' in M1 */ case '\'': f2p->epos = lp; break; #endif case '@': f2p->project = lp; break; case '%': f2p->lang = lp; break; case ':': f2p->form = lp; break; case '$': if (!BIT_ISSET(f2p->flags, F2_FLAGS_LEM_BY_NORM)) f2p->norm = lp; /* else ignore normalization because we got it from the "FORM" */ break; case '/': f2p->base = lp; break; case '+': if (*lp == '-') f2p->cont = lp; else if (*lp == '.') f2p->augment = lp; else vwarning2((char*)file,line,"%s: '+' in signature should be followed by '-' or '.'", err_lp); ++lp; break; case '#': if (*lp == '#') { ++lp; f2p->morph2 = lp; } else f2p->morph = lp; break; case '*': f2p->stem = lp; break; case '\\': disambig = lp; while (isalnum(*lp) || '\\' == *lp) ++lp; break; case '<': case ' ': case '\t': case 0: goto break_switch_loop; default: vwarning2((char*)file,line,"%s: parse error at '%c'", err_lp, field); ++ret; goto ret; } lp = field_end(lp); if (*lp) { field = *lp; *lp++ = '\0'; } } } } break_switch_loop: validate_pos((const char *)file, line, f2p->pos); validate_pos((const char *)file, line, f2p->epos); if (f2p->base) validate_base((const char *)file, line, f2p->base); #if 0 /* If lp is non-zero we didn't manage to parse the entire form: */ if (*lp) { vwarning2((char*)file,line,"%s: bad tense designator: only allowed with verb POS",err_lp); ret = -1; goto ret; } #endif /* field == '$' occurs when $ is the end of the lem, e.g., ana[to]PRP$ */ /* FIXME: THIS IS A POOR TEST BECAUSE IT FAILS ON ]N$#M1 */ if (field == '$') { if (!f2p->norm || !*f2p->norm) f2p->norm = f2p->cf; } if (BIT_ISSET(f2p->flags, F2_FLAGS_LEM_BY_NORM)) { if (f2p->norm && f2p->cf && !strcmp((char*)f2p->cf,(char*)f2p->norm)) { BIT_SET(f2p->flags, F2_FLAGS_NORM_IS_CF); f2p->cf = NULL; } } if (f2p->gw) { char *bs = strchr((char*)f2p->gw, '\\'); if (bs) { unsigned char *gwtmp = npool_copy(f2p->gw, f2_pool); bs = (char *)(gwtmp + (bs - (char*)f2p->gw)); *bs++ = '\0'; f2p->gw = gwtmp; if (*bs == 'i' || *bs == 't') { if ((!f2p->pos || *f2p->pos == 'V') && (!f2p->epos || *f2p->epos == 'V')) { if (*bs == 'i') f2p->epos = npool_copy((unsigned char *)"V/i",f2_pool); else f2p->epos = npool_copy((unsigned char *)"V/t",f2_pool); } else { vwarning2((char*)file,line,"%s: bad designator: only allowed with verb POS",err_lp); ret = -1; goto ret; } } else { vwarning2((char*)file,line,"%s: bad designator: only 'i' or 't' allowed",err_lp); ret = -1; goto ret; } } } ret: free(err_lp); /* '<' == *lp must be dealt with by caller */ if (isspace(*lp)) *lp++ = '\0'; if (!f2p->gw || !*f2p->gw) { if (f2p->sense && *f2p->sense) f2p->gw = f2p->sense; else f2p->gw = (unsigned char *)"1"; } clean_cf((char*)file, line, (unsigned char *)f2p->cf); clean_gw_sense((char*)file, line, (unsigned char *)f2p->gw); if (f2p->sense) clean_gw_sense((char*)file, line, (unsigned char *)f2p->sense); if (f2p->augment) { char buf[1024]; sprintf(buf,"%s%s%s",f2p->form,AUGMENT_STR,f2p->augment); f2p->form = npool_copy((unsigned char *)buf,f2_pool); } if (disambig) { char buf[1024]; if (*disambig == *(DISAMBIG_STR)) sprintf(buf,"%s%s",f2p->form,disambig); else sprintf(buf,"%s%s%s",f2p->form,DISAMBIG_STR,disambig); f2p->form = npool_copy((unsigned char *)buf,f2_pool); } if (f2p->cf && strchr((char*)f2p->cf,' ')) BIT_SET(f2p->flags, F2_FLAGS_IS_PSU); phase = saved_phase; with_textid = saved_with_textid; return (ret < 0) ? -1 : (lp - orig_lp); }
void makeit(void) { wcsstruct *wcs; fieldstruct **fields, *field; psfstruct **cpsf, *psf; setstruct *set, *set2; contextstruct *context, *fullcontext; struct tm *tm; char str[MAXCHAR]; char **incatnames, *pstr; float **psfbasiss, *psfsteps, *psfbasis, *basis, psfstep, step; int c,i,p, ncat, ext, next, nmed, nbasis; /* Install error logging */ error_installfunc(write_error); incatnames = prefs.incat_name; ncat = prefs.ncat; /* Processing start date and time */ thetime = time(NULL); tm = localtime(&thetime); sprintf(prefs.sdate_start,"%04d-%02d-%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday); sprintf(prefs.stime_start,"%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); NFPRINTF(OUTPUT, ""); QPRINTF(OUTPUT, "----- %s %s started on %s at %s with %d thread%s\n\n", BANNER, MYVERSION, prefs.sdate_start, prefs.stime_start, prefs.nthreads, prefs.nthreads>1? "s":""); /* End here if no filename has been provided */ if (!ncat) { /*-- Processing end date and time */ thetime2 = time(NULL); tm = localtime(&thetime2); sprintf(prefs.sdate_end,"%04d-%02d-%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday); sprintf(prefs.stime_end,"%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); prefs.time_diff = difftime(thetime2, thetime); /*-- Write XML */ if (prefs.xml_flag) { init_xml(0); write_xml(prefs.xml_name); end_xml(); } return; } /* Create an array of PSFs (one PSF for each extension) */ QMALLOC(fields, fieldstruct *, ncat); NFPRINTF(OUTPUT, ""); QPRINTF(OUTPUT, "----- %d input catalogues:\n", ncat); for (c=0; c<ncat; c++) { fields[c] = field_init(incatnames[c]); QPRINTF(OUTPUT, "%-20.20s: \"%-16.16s\" %3d extension%s %7d detection%s\n", fields[c]->rcatname, fields[c]->ident, fields[c]->next, fields[c]->next>1 ? "s":"", fields[c]->ndet, fields[c]->ndet>1 ? "s":""); } QPRINTF(OUTPUT, "\n"); if (prefs.xml_flag) init_xml(ncat); makeit_body(fields, &context, &fullcontext, 1); next = fields[0]->next; /* Write XML */ if (prefs.xml_flag) { NFPRINTF(OUTPUT, "Writing XML file..."); write_xml(prefs.xml_name); end_xml(); } /* Save result */ for (c=0; c<ncat; c++) { sprintf(str, "Saving PSF model and metadata for %s...", fields[c]->rtcatname); NFPRINTF(OUTPUT, str); /*-- Create a file name with a "PSF" extension */ if (*prefs.psf_dir) { if ((pstr = strrchr(incatnames[c], '/'))) pstr++; else pstr = incatnames[c]; sprintf(str, "%s/%s", prefs.psf_dir, pstr); } else strcpy(str, incatnames[c]); if (!(pstr = strrchr(str, '.'))) pstr = str+strlen(str); sprintf(pstr, "%s", prefs.psf_suffix); field_psfsave(fields[c], str); /* Create homogenisation kernels */ if (prefs.homobasis_type != HOMOBASIS_NONE) { for (ext=0; ext<next; ext++) { if (next>1) sprintf(str, "Computing homogenisation kernel for %s[%d/%d]...", fields[c]->rtcatname, ext+1, next); else sprintf(str, "Computing homogenisation kernel for %s...", fields[c]->rtcatname); NFPRINTF(OUTPUT, str); if (*prefs.homokernel_dir) { if ((pstr = strrchr(incatnames[c], '/'))) pstr++; else pstr = incatnames[c]; sprintf(str, "%s/%s", prefs.homokernel_dir, pstr); } else strcpy(str, incatnames[c]); if (!(pstr = strrchr(str, '.'))) pstr = str+strlen(str); sprintf(pstr, "%s", prefs.homokernel_suffix); psf_homo(fields[c]->psf[ext], str, prefs.homopsf_params, prefs.homobasis_number, prefs.homobasis_scale, ext, next); } } #ifdef HAVE_PLPLOT /* Plot diagnostic maps for all catalogs */ cplot_ellipticity(fields[c]); cplot_fwhm(fields[c]); cplot_moffatresi(fields[c]); cplot_asymresi(fields[c]); cplot_counts(fields[c]); cplot_countfrac(fields[c]); cplot_modchi2(fields[c]); cplot_modresi(fields[c]); #endif /*-- Update XML */ if (prefs.xml_flag) update_xml(fields[c]); } /* Processing end date and time */ thetime2 = time(NULL); tm = localtime(&thetime2); sprintf(prefs.sdate_end,"%04d-%02d-%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday); sprintf(prefs.stime_end,"%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); prefs.time_diff = difftime(thetime2, thetime); /* Free memory */ for (c=0; c<ncat; c++) field_end(fields[c]); free(fields); if (context->npc) context_end(fullcontext); context_end(context); return; }