int main(int argc, char *argv[]){ check4running(PIDFILE, NULL); initial_setup(); Global_parameters = parse_args(argc, argv); assert(Global_parameters); if(!get_shm_block(&sdat, ClientSide) || !check_shm_block(&sdat)){ ERRX("Can't get SHM block!"); } #ifndef EBUG PRINT(_("Test multicast connection\n")); double last = M_time; WAIT_EVENT((fabs(M_time - last) > 0.02), 5.); if(tmout && fabs(M_time - last) < 4.) ERRX(_("Multicasts stale!")); #endif signal(SIGTERM, signals); // kill (-15) signal(SIGHUP, SIG_IGN); // hup - daemon signal(SIGINT, signals); // ctrl+C signal(SIGQUIT, signals); // ctrl+\ . signal(SIGTSTP, SIG_IGN); // ctrl+Z setbuf(stdout, NULL); setup_pins(); if(Global_parameters->absmove && gotozero()) ERRX(_("Can't locate zero-endswitch")); if(Global_parameters->gotoangle > -360. && Global_parameters->gotoangle < 360.){ if(Global_parameters->absmove) Global_parameters->gotoangle += PA_ZEROVAL; if(gotoangle(Global_parameters->gotoangle)) ERRX(_("Can't move for given angle")); } stepper_process(); return 0; }
static void receiver(const int fd, const char *host, const char *port, size_t n, bool conn, bool bug) { int s; ssize_t l; size_t seq; struct message msg; struct pollfd pfd; socklen_t slen; s = getsocket(host, port, bind, &slen, bug); pfd.fd = s; pfd.events = POLLIN; /* Tell I'm ready */ synchronize(fd, false); for (seq = 0; seq < n; seq++) { if (poll(&pfd, 1, 10000) == -1) ERRX(EXIT_FAILURE, "poll (%s)", strerror(errno)); l = conn ? recv(s, &msg, sizeof(msg), 0) : recvfrom(s, &msg, sizeof(msg), 0, (void *)&ss, &slen); if (l == -1) ERRX(EXIT_FAILURE, "recv (%s)", strerror(errno)); if (debug) show("got", &msg); if (seq != msg.seq) ERRX(EXIT_FAILURE, "seq: expect=%zu actual=%zu", seq, msg.seq); } /* Tell I'm finished */ synchronize(fd, false); }
static int synchronize(const int fd, bool waiter) { int syncmsg = 0; int r; struct pollfd pfd; if (waiter) { pfd.fd = fd; pfd.events = POLLIN; /* We use poll to avoid lock up when the peer died unexpectedly */ r = poll(&pfd, 1, 10000); if (r == -1) ERRX(EXIT_FAILURE, "poll (%s)", strerror(errno)); if (r == 0) /* Timed out */ return -1; if (read(fd, &syncmsg, sizeof(syncmsg)) == -1) ERRX(EXIT_FAILURE, "read (%s)", strerror(errno)); } else { if (write(fd, &syncmsg, sizeof(syncmsg)) == -1) ERRX(EXIT_FAILURE, "write (%s)", strerror(errno)); } return 0; }
static int getsocket(const char *host, const char *port, int (*f)(int, const struct sockaddr *, socklen_t), socklen_t *slen, bool bug) { int e, s, lasterrno = 0; struct addrinfo hints, *ai0, *ai; const char *cause = "?"; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; e = getaddrinfo(host, port, &hints, &ai0); if (e) ERRX(EXIT_FAILURE, "Can't resolve %s:%s (%s)", host, port, gai_strerror(e)); s = -1; for (ai = ai0; ai; ai = ai->ai_next) { s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (s == -1) { lasterrno = errno; cause = "socket"; continue; } if (allowv4mapped(s, ai) == -1) { cause = "allow v4 mapped"; goto out; } if ((*f)(s, ai->ai_addr, ai->ai_addrlen) == -1) { cause = f == bind ? "bind" : "connect"; goto out; } if ((f == bind || f == connector) && addmc(s, ai, bug) == -1) { cause = "join group"; goto out; } *slen = ai->ai_addrlen; break; out: lasterrno = errno; close(s); s = -1; continue; } freeaddrinfo(ai0); if (s == -1) ERRX(EXIT_FAILURE, "%s (%s)", cause, strerror(lasterrno)); return s; }
static void run(const char *host, const char *port, size_t n, bool conn, bool bug) { pid_t pid; int status; int syncfds[2]; int error; if (socketpair(AF_UNIX, SOCK_STREAM, 0, syncfds) == -1) ERRX(EXIT_FAILURE, "socketpair (%s)", strerror(errno)); switch ((pid = fork())) { case 0: receiver(syncfds[0], host, port, n, conn, bug); return; case -1: ERRX(EXIT_FAILURE, "fork (%s)", strerror(errno)); default: error = sender(syncfds[1], host, port, n, conn, bug); again: switch (waitpid(pid, &status, WNOHANG)) { case -1: ERRX(EXIT_FAILURE, "wait (%s)", strerror(errno)); case 0: if (error == 0) /* * Receiver is still alive, but we know * it will exit soon. */ goto again; if (kill(pid, SIGTERM) == -1) ERRX(EXIT_FAILURE, "kill (%s)", strerror(errno)); goto again; default: if (WIFSIGNALED(status)) { if (WTERMSIG(status) == SIGTERM) ERRX0(EXIT_FAILURE, "receiver failed and was killed" \ "by sender"); else ERRX(EXIT_FAILURE, "receiver got signaled (%s)", strsignal(WTERMSIG(status))); } else if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) ERRX(EXIT_FAILURE, "receiver exited with status %d", WEXITSTATUS(status)); } else { ERRX(EXIT_FAILURE, "receiver exited with unexpected status %d", status); } break; } return; } }
static int sender(const int fd, const char *host, const char *port, size_t n, bool conn, bool bug) { int s; ssize_t l; struct message msg; socklen_t slen; s = getsocket(host, port, conn ? connect : connector, &slen, bug); /* Wait until receiver gets ready. */ if (synchronize(fd, true) == -1) return -1; for (msg.seq = 0; msg.seq < n; msg.seq++) { #ifdef CLOCK_MONOTONIC if (clock_gettime(CLOCK_MONOTONIC, &msg.ts) == -1) ERRX(EXIT_FAILURE, "clock (%s)", strerror(errno)); #else struct timeval tv; if (gettimeofday(&tv, NULL) == -1) ERRX(EXIT_FAILURE, "clock (%s)", strerror(errno)); msg.ts.tv_sec = tv.tv_sec; msg.ts.tv_nsec = tv.tv_usec * 1000; #endif if (debug) show("sending", &msg); l = conn ? send(s, &msg, sizeof(msg), 0) : sendto(s, &msg, sizeof(msg), 0, (void *)&ss, slen); if (l == -1) ERRX(EXIT_FAILURE, "send (%s)", strerror(errno)); usleep(100); } /* Wait until receiver finishes its work. */ if (synchronize(fd, true) == -1) return -1; return 0; }
int main(int argc, char *argv[]) { struct nl_sock *sock; struct nl_cache *cache; struct nl_dump_params params = { .dp_type = NL_DUMP_LINE, .dp_fd = stdout, }; if ((sock = nl_socket_alloc()) == 0) ERRX("Failed nl_socket_alloc"); if (genl_connect(sock)) ERRX("Failed genl_connect"); if (genl_ctrl_alloc_cache(sock, &cache)) ERRX("Failed genl_ctrl_alloc_cache"); nl_cache_dump(cache, ¶ms); return 0; }
/** * build IMAGE image from data array indata */ IMAGE *buildFITSfromdat(size_t h, size_t w, int dtype, uint8_t *indata){ size_t stride = 0; double (*fconv)(uint8_t *data) = NULL; double ubyteconv(uint8_t *data){return (double)*data;} double ushortconv(uint8_t *data){return (double)*(int16_t*)data;} double ulongconv(uint8_t *data){return (double)*(uint32_t*)data;} double ulonglongconv(uint8_t *data){return (double)*(uint64_t*)data;} double floatconv(uint8_t *data){return (double)*(float*)data;} IMAGE *out = newFITS(h, w, dtype); switch (dtype){ case BYTE_IMG: stride = 1; fconv = ubyteconv; break; case SHORT_IMG: stride = 2; fconv = ushortconv; break; case LONG_IMG: stride = 4; fconv = ulongconv; break; case FLOAT_IMG: stride = 4; fconv = floatconv; break; case LONGLONG_IMG: fconv = ulonglongconv; stride = 8; break; case DOUBLE_IMG: memcpy(out->data, indata, sizeof(double)*w*h); return out; break; default: /// Неправильный тип данных ERRX(_("Wrong data type")); } size_t y, W = w*stride; Item *data = out->data; OMP_FOR(shared(data)) for(y = 0; y < h; ++y){ Item *dout = &data[y*w]; uint8_t *din = &indata[y*W]; size_t x; for(x = 0; x < w; ++x, din += stride) *dout++ = fconv(din); } return out; }
/* * makes array of pipeline parameters * if any found, return TRUE * else return FALSE */ bool get_pipeline_params(){ int i, N; char **p = G.conv; Filter *f; for(N = 0; *p; ++N, ++p); farray_size = N; if(N == 0) return FALSE; farray = MALLOC(Filter*, farray_size); p = G.conv; for(i = 0; i < N; ++i, ++p){ DBG("filter: %s", *p); if(!(f = parse_filter(*p))){ /// "Неправильно заданы параметры конвейера" ERRX(_("Wrong pipeline parameters!")); } farray[i] = f; } return TRUE; }
/** * Mmap file to a memory area * * @param filename (i) - name of file to mmap * @return stuct with mmap'ed file or die */ mmapbuf *My_mmap(char *filename){ int fd; char *ptr; size_t Mlen; struct stat statbuf; if(!filename) ERRX(_("No filename given!")); if((fd = open(filename, O_RDONLY)) < 0) ERR(_("Can't open %s for reading"), filename); if(fstat (fd, &statbuf) < 0) ERR(_("Can't stat %s"), filename); Mlen = statbuf.st_size; if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) ERR(_("Mmap error for input")); if(close(fd)) ERR(_("Can't close mmap'ed file")); mmapbuf *ret = MALLOC(mmapbuf, 1); ret->data = ptr; ret->len = Mlen; return ret; }
/** * Run daemon service */ void daemonize(char *port){ FNAME(); int sock = -1; struct addrinfo hints, *res, *p; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; if(getaddrinfo(NULL, port, &hints, &res) != 0){ ERR("getaddrinfo"); } struct sockaddr_in *ia = (struct sockaddr_in*)res->ai_addr; char str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &(ia->sin_addr), str, INET_ADDRSTRLEN); // loop through all the results and bind to the first we can for(p = res; p != NULL; p = p->ai_next){ if((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){ WARN("socket"); continue; } int reuseaddr = 1; if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1){ ERR("setsockopt"); } if(bind(sock, p->ai_addr, p->ai_addrlen) == -1){ close(sock); WARN("bind"); continue; } break; // if we get here, we have a successfull connection } if(p == NULL){ putlog("failed to bind socket, exit"); // looped off the end of the list with no successful bind ERRX("failed to bind socket"); } freeaddrinfo(res); daemon_(sock); close(sock); putlog("socket closed, exit"); signals(0); }
IMAGE *process_pipeline(IMAGE *image){ if(!image){ /// "Не задано входное изображение" ERRX(_("No input image given")); } if(!farray || !farray_size){ /// "Не заданы параметры конвейера" WARNX(_("No pipeline parameters given")); } size_t i; Filter **far = farray; IMAGE *in = copyFITS(image); // copy original image to leave it unchanged IMAGE *processed = NULL; for(i = 0; i < farray_size; ++i, ++far){ Filter *f = *far; DBG("Got filter #%d: w=%d, h=%d, sx=%g, sy=%g\n", f->FilterType, f->w, f->h, f->sx, f->sy); printf("try filter %zd\n", i); Itmarray oarg = {NULL, 0}; processed = f->imfunc(in, f, &oarg); /// "Ошибка в обработке конвейера" if(!processed) ERRX(_("Error on pipeline processing!")); // TODO: what should I do with oarg??? if(oarg.size){ size_t i, l = oarg.size; //if(verbose_level){ green("got oarg: \n"); for(i = 0; i < l; ++i){ printf("%5zd: %g\n", i, oarg.data[i]); } //} char tabname[80]; snprintf(tabname, 80, "%s_CONVERSION", f->name); FITStable *tab = table_new(processed, tabname); if(tab){ table_column col = { .width = sizeof(int32_t), .repeat = l, .coltype = TINT }; int32_t *levls = MALLOC(int32_t, l); for(i = 0; i < l; ++i) levls[i] = (int32_t) i; col.contents = levls; sprintf(col.colname, "level"); *col.unit = 0; table_addcolumn(tab, &col); FREE(levls); col.contents = oarg.data; col.coltype = TDOUBLE; col.width = sizeof(double), sprintf(col.colname, "value"); sprintf(col.unit, "ADU"); table_addcolumn(tab, &col); printf("Create table:\n"); table_print(tab); } FREE(oarg.data); } processed->keylist = in->keylist; char changes[FLEN_CARD]; snprintf(changes, FLEN_CARD, "HISTORY modified by routine %s", f->name); list_add_record(&(processed->keylist), changes); //list_print(processed->keylist); in->keylist = NULL; // prevent deleting global keylist imfree(&in); in = processed; } return processed; }
Filter *parse_filter(char *pars){ Filter *fltr; int idx = -1; pipepars popts; mysuboption pipeopts[] = { // help for given conversion {"help", NO_ARGS, arg_none, &popts.help}, // type of conversion {"type", NEED_ARG, arg_string, &popts.ftype}, // radius of median filter {"r", NEED_ARG, arg_int, &popts.xsz}, // sigmax, sigmay for gauss/lapgauss {"sx", NEED_ARG, arg_double, &popts.xhw}, {"sy", NEED_ARG, arg_double, &popts.yhw}, // & window size for them {"w", NEED_ARG, arg_int, &popts.xsz}, {"h", NEED_ARG, arg_int, &popts.ysz}, // posterisation {"nsteps",NEED_ARG,arg_int, &popts.xsz}, {"scale",NEED_ARG, arg_string, &popts.scale}, end_suboption }; memset(&popts, 0, sizeof(pipepars)); if(!get_suboption(pars, pipeopts)){ return NULL; }else{ if(!popts.ftype){ // no type given /// "Необходимо по крайней мере задать параметр 'type', например: '-p type=help'" ERRX(_("You should at least give parameter 'type', for example: '-p type=help'")); } DBG("type: %s", popts.ftype); if(strcmp(popts.ftype, "help") == 0){ // info about pipeline names show_pipeline_pars(); } int i = 0; while(filter_names[i].parname){ if(!strcmp(filter_names[i].parname, popts.ftype)){ idx = i; break; } ++i; } if(idx == -1){ // wrong type /// "Неправильный параметр 'type' конвейера" WARNX(_("Wrong pipeline 'type' parameter: %s"), popts.ftype); show_pipeline_pars(); } } if(popts.help){ // help about current filter options showparhelp(idx); } fltr = MALLOC(Filter, 1); fltr->FilterType = filter_names[idx].FilterType; fltr->name = strdup(filter_names[idx].parname); popts.imfunc = filter_names[idx].imfunc; DBG("idx: %d, ftype: %d", idx, fltr->FilterType); // check parameters & fill Filer fields if(popts.imfunc == get_median || popts.imfunc == get_adaptive_median){ fltr->w = popts.xsz; }else if(popts.imfunc == DiffFilter && (fltr->FilterType == LAPGAUSS || fltr->FilterType == GAUSS)){ if(popts.xsz < 5){ // "Ширина фильтра изменена на 5" WARNX(_("Filter window width changed to 5")); popts.xsz = 5; } if(popts.ysz < 5){ // "Высота фильтра изменена на 5" WARNX(_("Filter window height changed to 5")); popts.ysz = 5; } if(popts.xhw < 1. || popts.yhw < 1.){ /// "Полуширина фильтра должна быть не меньше 1." ERRX(_("Filter FWHM should be not less than 1.")); } fltr->w = popts.xsz; fltr->h = popts.ysz; fltr->sx = popts.xhw; fltr->sy = popts.yhw; }else if(popts.imfunc == StepFilter){ // check levels & type if(popts.xsz < 2 || popts.xsz > 255){ /// "Количество уровней градаций яркости должно быть от 2 до 255" ERRX(_("Brightness levels amount shoul be from 2 to 255")); } fltr->w = popts.xsz; int i = 0, idx = -1; DBG("name: %s", popts.scale); if(!popts.scale){ /// "Не указан параметр scale" ERRX(_("You should set 'scale' parameter")); } while(scales[i].name){ if(!strcmp(popts.scale, scales[i].name)){ idx = i; break; } ++i; } if(idx == -1){ /// "Параметры фильтра постеризации должны быть такими:\n%s" ERRX(_("Posterisation filter parameters should be:\n%s"), stepargs); } DBG("idx: %d", idx); fltr->h = scales[idx].type; } fltr->imfunc = popts.imfunc; DBG("Got filter #%d: w=%d, h=%d, sx=%g, sy=%g\n", fltr->FilterType, fltr->w, fltr->h, fltr->sx, fltr->sy); return fltr; }
/** * add to table 'tbl' column 'column' * Be carefull all fields of 'column' exept of 'format' should be filled * - if data is character array, 'width' should be equal 0 * - all input data will be copied, so caller should run 'free' after this function! */ FITStable *table_addcolumn(FITStable *tbl, table_column *column){ FNAME(); if(!tbl || !column || !column->contents) return NULL; long nrows = column->repeat; int width = column->width; if(tbl->nrows < nrows) tbl->nrows = nrows; size_t datalen = nrows * width, cols = ++tbl->ncols; char *curformat = column->format; DBG("add column; width: %d, nrows: %ld, name: %s", width, nrows, column->colname); /*void convchar(){ // count maximum length of strings in array char **charr = (char**)column->contents, *dptr = charr; size_t n, N = column->repeat; for(n = 0; n < N; ++n){ if(strlen( if(*dptr++ == 0){ --processed; if(len > maxlen) maxlen = len; len = 0; } else{ ++len; } } }*/ #define CHKLEN(type) do{if(width != sizeof(type)) datalen = sizeof(type) * nrows;}while(0) switch(column->coltype){ case TBIT: snprintf(curformat, FLEN_FORMAT, "%ldX", nrows); CHKLEN(int8_t); break; case TBYTE: snprintf(curformat, FLEN_FORMAT, "%ldB", nrows); CHKLEN(int8_t); break; case TLOGICAL: snprintf(curformat, FLEN_FORMAT, "%ldL", nrows); CHKLEN(int8_t); break; case TSTRING: if(width == 0){ snprintf(curformat, FLEN_FORMAT, "%ldA", nrows); datalen = nrows; }else snprintf(curformat, FLEN_FORMAT, "%ldA%d", nrows, width); break; case TSHORT: snprintf(curformat, FLEN_FORMAT, "%ldI", nrows); CHKLEN(int16_t); break; case TLONG: snprintf(curformat, FLEN_FORMAT, "%ldJ", nrows); CHKLEN(int32_t); break; case TLONGLONG: snprintf(curformat, FLEN_FORMAT, "%ldK", nrows); CHKLEN(int64_t); break; case TFLOAT: snprintf(curformat, FLEN_FORMAT, "%ldE", nrows); CHKLEN(float); break; case TDOUBLE: snprintf(curformat, FLEN_FORMAT, "%ldD", nrows); CHKLEN(double); break; case TCOMPLEX: snprintf(curformat, FLEN_FORMAT, "%ldM", nrows); if(width != sizeof(float)*2) datalen = sizeof(float) * nrows * 2; break; case TDBLCOMPLEX: snprintf(curformat, FLEN_FORMAT, "%ldM", nrows); if(width != sizeof(double)*2) datalen = sizeof(double) * nrows * 2; break; case TINT: snprintf(curformat, FLEN_FORMAT, "%ldJ", nrows); CHKLEN(int32_t); break; case TSBYTE: snprintf(curformat, FLEN_FORMAT, "%ldS", nrows); CHKLEN(int8_t); break; case TUINT: snprintf(curformat, FLEN_FORMAT, "%ldV", nrows); CHKLEN(int32_t); break; case TUSHORT: snprintf(curformat, FLEN_FORMAT, "%ldU", nrows); CHKLEN(int16_t); break; default: WARNX(_("Unsupported column data type!")); return NULL; } DBG("new size: %ld, old: %ld", sizeof(table_column)*cols, sizeof(table_column)*(cols-1)); if(!(tbl->columns = realloc(tbl->columns, sizeof(table_column)*cols))) ERRX("malloc"); table_column *newcol = &(tbl->columns[cols-1]); memcpy(newcol, column, sizeof(table_column)); newcol->contents = calloc(datalen, 1); if(!newcol->contents) ERRX("malloc"); DBG("copy %zd bytes", datalen); if(column->coltype == TSTRING && width){ long n; char **optr = (char**)newcol->contents, **iptr = (char**)column->contents; for(n = 0; n < nrows; ++n, ++optr, ++iptr) *optr = strdup(*iptr); }else memcpy(newcol->contents, column->contents, datalen); return tbl; }
/** * add FITS table to image structure */ FITStable *table_read(IMAGE *img, fitsfile *fp){ int ncols, i; long nrows; char extname[FLEN_VALUE]; #define TRYRET(f, ...) do{TRYFITS(f, fp, __VA_ARGS__); if(fitsstatus) goto ret;}while(0) TRYRET(fits_get_num_rows, &nrows); TRYRET(fits_get_num_cols, &ncols); TRYRET(fits_read_key, TSTRING, "EXTNAME", extname, NULL); DBG("Table named %s with %ld rows and %d columns", extname, nrows, ncols); FITStable *tbl = table_new(img, extname); if(!tbl) return NULL; for(i = 1; i <= ncols; ++i){ int typecode; long repeat, width; FITSFUN(fits_get_coltype, fp, i, &typecode, &repeat, &width); if(fitsstatus){ WARNX(_("Can't read column %d!"), i); continue; } DBG("typecode=%d, repeat=%ld, width=%ld", typecode, repeat, width); table_column col = {.repeat = repeat, .width = width, .coltype = typecode}; void *array = malloc(width*repeat); if(!array) ERRX("malloc"); int anynul; int64_t nullval = 0; int j; for(j = 0; j < repeat; ++j){ FITSFUN(fits_read_col, fp, typecode, i, j=1, 1, 1, (void*)nullval, array, &anynul); if(fitsstatus){ WARNX(_("Can't read column %d row %d!"), i, j); continue; } } DBG("done"); continue; col.contents = array; char keyword[FLEN_KEYWORD]; int stat = 0; fits_make_keyn("TTYPE", i, keyword, &stat); if(stat){WARNX("???"); stat = 0;} fits_read_key(fp, TSTRING, keyword, col.colname, NULL, &stat); if(stat){ sprintf(col.colname, "noname"); stat = 0;} fits_make_keyn("TUNIT", i, keyword, &stat); if(stat){WARNX("???"); stat = 0;} fits_read_key(fp, TSTRING, keyword, col.unit, NULL, &stat); if(stat) *col.unit = 0; DBG("Column, cont[2]=%d, type=%d, w=%ld, r=%ld, nm=%s, u=%s", ((int*)col.contents)[2], col.coltype, col.width, col.repeat, col.colname, col.unit); //table_addcolumn(tbl, &col); FREE(array); } // DBG("fits_create_tbl nrows=%zd, ncols=%zd, colnms[0]=%s, formats[0]=%s, " // "units[0]=%s, name=%s", tbl->nrows, cols, tbl->colnames[0], tbl->formats[0], tbl->units[0], tbl->tabname); #undef TRYRET ret: if(fitsstatus){ tablefree(&tbl); --img->tables->amount; } return tbl; }
int main(int argc, char **argv){ int i, j, L; mmapbuf *input; initial_setup(); parce_args(argc, argv); if(!G.ifile){ ERRX("You shold give input file name\n"); return(-1); } if(G.format) DBG("Format: %s\n", G.format); else{ DBG("No format defined, use \"%%s.%%d\"\n"); G.format = "%s.%d"; } if(G.nparts) DBG("Use first %d copies of list\n", G.nparts); else DBG("Use all list given\n"); if(!G.list){ WARNX("Error! You should say\n\t\t%s -L list\n", __progname); ERR("\twhere \"list\" is a comma-separated list of sheets\n"); return(-1); } L = build_list(); DBG("Found %d sheets in list:\n", L); if(L == 0){ ERRX("Error: empty list\n"); return(-1); } for(i = 0; i < L; i++) DBG("\titem %d: %s\n", i, List[i]); if(!(input = My_mmap(G.ifile))){ ERRX("A strange error: can't mmap input file\n"); return(-1); } char *iptr = input->data, *oldptr = iptr; i = 0; char comp[32], val[32]; int N1, N2; while((iptr = strstr(iptr, "$Comp\n"))){ DBG("%dth component: ", ++i); iptr = strstr(iptr, "\nL "); if(!iptr) break; iptr += 3; if(sscanf(iptr, "%s %s\n", comp, val) != 2) continue; DBG("component %s with label %s\n", comp, val); iptr = strstr(iptr, "\nU "); if(!iptr) break; iptr += 3; if(sscanf(iptr, "%d %d %s\n",&N1,&N2,comp) != 3) continue; DBG("N1 = %d; N2 = %d; comp label: %s\n",N1,N2,comp); iptr = strstr(iptr, "\nF"); // go to line "F 0" if(!iptr) break; iptr++; // printout all what was before: oldptr = printdata(oldptr, iptr); for(j = 0; j < L; j++){ printf("AR Path=\"/%s/%s\" Ref=\"", List[j], comp); printf(G.format, val, j+1); printf("\" Part=\"1\"\n"); } } // printout the rest of file if(!iptr) iptr = input->data + input->len; printdata(oldptr, iptr); My_munmap(input); return 0; }