ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.4
Committed: Thu Jun 26 00:58:11 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.3: +3 -1 lines
Log Message:
Abstracted process and path handling for Windows.
Renamed FLOAT to RREAL because of conflict on Windows.
Added conditional compiles for some signal handlers.

File Contents

# User Rev Content
1 greg 3.1 #ifndef lint
2 greg 3.3 static const char RCSid[] = "$Id";
3 greg 3.1 #endif
4     /*
5     * Radiance object animation program
6     *
7     * Main program and control file handling.
8     *
9     * See ranimove.h and the ranimove(1) man page for details.
10     */
11    
12 greg 3.2 #include "copyright.h"
13 greg 3.1
14     #include "ranimove.h"
15 greg 3.3 #include <time.h>
16 schorsch 3.4 #ifndef _WIN32
17     #include <sys/time.h>
18     #endif
19 greg 3.1 #include <ctype.h>
20    
21     int NVARS = NV_INIT; /* total number of variables */
22    
23     VARIABLE vv[] = VV_INIT; /* variable-value pairs */
24    
25     extern int nowarn; /* don't report warnings? */
26     int silent = 0; /* run silently? */
27    
28     int quickstart = 0; /* time initial frame as well? */
29    
30     int nprocs = 1; /* number of rendering processes */
31    
32     int rtperfrm = 60; /* seconds to spend per frame */
33    
34     double ndthresh = 2.; /* noticeable difference threshold */
35     int ndtset = 0; /* user threshold -- stop when reached? */
36    
37     int fbeg = 1; /* starting frame */
38     int fend = 0; /* ending frame */
39     int fcur; /* current frame being rendered */
40    
41     char lorendoptf[32]; /* low quality options file */
42     RAYPARAMS lorendparams; /* low quality rendering parameters */
43     char hirendoptf[32]; /* high quality options file */
44     RAYPARAMS hirendparams; /* high quality rendering parameters */
45     RAYPARAMS *curparams; /* current parameter settings */
46     int twolevels; /* low and high quality differ */
47    
48     double mblur; /* vflt(MBLUR) */
49     double rate; /* vflt(RATE) */
50    
51     char objtmpf[32]; /* object temporary file */
52    
53     struct ObjMove *obj_move; /* object movements */
54    
55     int haveprio = 0; /* high-level saliency specified */
56    
57     int gargc; /* global argc for printargs */
58     char **gargv; /* global argv for printargs */
59    
60    
61     int
62     main(argc, argv)
63     int argc;
64     char *argv[];
65     {
66     int explicate = 0;
67     char *cfname;
68     int i;
69    
70     progname = argv[0]; /* get arguments */
71     gargc = argc;
72     gargv = argv;
73     for (i = 1; i < argc && argv[i][0] == '-'; i++)
74     switch (argv[i][1]) {
75     case 't': /* seconds per frame */
76     rtperfrm = atoi(argv[++i]);
77     break;
78     case 'd': /* noticeable difference */
79     ndthresh = atof(argv[++i]);
80     ndtset = 1;
81     break;
82     case 'e': /* print variables */
83     explicate++;
84     break;
85     case 's': /* silent running */
86     silent++;
87     break;
88     case 'q': /* start quickly */
89     quickstart++;
90     break;
91     case 'w': /* turn off warnings */
92     nowarn++;
93     break;
94     case 'f': /* frame range */
95     switch (sscanf(argv[++i], "%d,%d", &fbeg, &fend)) {
96     case 2:
97     if ((fbeg <= 0 | fend < fbeg))
98     goto userr;
99     break;
100     case 1:
101     if (fbeg <= 0)
102     goto userr;
103     fend = 0;
104     break;
105     default:
106     goto userr;
107     }
108     break;
109     case 'n': /* number of processes */
110     nprocs = atoi(argv[++i]);
111     break;
112     default:
113     goto userr;
114     }
115     if (rtperfrm <= 0) {
116     if (!ndtset)
117     error(USER, "specify -d jnd with -t 0");
118     rtperfrm = 7*24*3600;
119     }
120     if (i != argc-1)
121     goto userr;
122     cfname = argv[i];
123     /* load variables */
124     loadvars(cfname);
125     /* check variables */
126     checkvalues();
127     /* load RIF if any */
128     if (vdef(RIF))
129     getradfile(vval(RIF));
130     /* set defaults */
131     setdefaults();
132     /* print variables */
133     if (explicate)
134     printvars(stdout);
135     /* run animation */
136     if (nprocs > 0)
137     animate();
138     /* all done */
139     if (lorendoptf[0])
140     unlink(lorendoptf);
141     if (hirendoptf[0])
142     unlink(hirendoptf);
143     if (objtmpf[0])
144     unlink(objtmpf);
145     return(0);
146     userr:
147     fprintf(stderr,
148     "Usage: %s [-n nprocs][-f beg,end][-t sec][-d jnd][-s][-w][-e] anim_file\n",
149     progname);
150     quit(1);
151     }
152    
153    
154     void
155     eputs(s) /* put string to stderr */
156     register char *s;
157     {
158     static int midline = 0;
159    
160     if (!*s)
161     return;
162     if (!midline++) {
163     fputs(progname, stderr);
164     fputs(": ", stderr);
165     }
166     fputs(s, stderr);
167     if (s[strlen(s)-1] == '\n') {
168     fflush(stderr);
169     midline = 0;
170     }
171     }
172    
173    
174     void
175     setdefaults() /* set default values */
176     {
177     int nviews;
178     int decades;
179     char buf[256];
180     int i;
181    
182     if (!vdef(OCTREEF)) {
183     sprintf(errmsg, "%s or %s must be defined",
184     vnam(OCTREEF), vnam(RIF));
185     error(USER, errmsg);
186     }
187     if (!vdef(VIEWFILE)) {
188     sprintf(errmsg, "%s must be defined", vnam(VIEWFILE));
189     error(USER, errmsg);
190     }
191     nviews = countviews();
192     if (!nviews)
193     error(USER, "no views in view file");
194     if (!vdef(END)) {
195     if (nviews == 1) {
196     sprintf(errmsg, "%s must be defined for single view",
197     vnam(END));
198     error(USER, errmsg);
199     }
200     sprintf(buf, "%d", nviews);
201     vval(END) = savqstr(buf);
202     vdef(END)++;
203     }
204     if (!fend)
205     fend = vint(END);
206     if (fbeg > fend)
207     error(USER, "begin after end");
208     if (!vdef(BASENAME)) {
209     decades = (int)log10((double)vint(END)) + 1;
210     if (decades < 3) decades = 3;
211     sprintf(buf, "frame%%0%dd", decades);
212     vval(BASENAME) = savqstr(buf);
213     vdef(BASENAME)++;
214     }
215     if (!vdef(RATE)) {
216     vval(RATE) = "8";
217     vdef(RATE)++;
218     }
219     rate = vflt(RATE);
220     if (!vdef(RESOLUTION)) {
221     vval(RESOLUTION) = "640";
222     vdef(RESOLUTION)++;
223     }
224     if (!vdef(MBLUR)) {
225     vval(MBLUR) = "0";
226     vdef(MBLUR)++;
227     }
228     mblur = vflt(MBLUR);
229     if (mblur > 1.)
230     mblur = 1.;
231     /* set up objects */
232     if (vdef(MOVE)) {
233     obj_move = (struct ObjMove *)malloc(
234     sizeof(struct ObjMove)*vdef(MOVE) );
235     if (obj_move == NULL)
236     error(SYSTEM, "out of memory in setdefaults");
237     for (i = 0; i < vdef(MOVE); i++)
238     setmove(&obj_move[i], nvalue(MOVE, i));
239     }
240     /* set up high quality options */
241     setrendparams(hirendoptf, vval(HIGHQ));
242     ray_save(&hirendparams);
243     /* set up low quality options */
244     setrendparams(lorendoptf, vval(LOWQ));
245     ray_save(&lorendparams);
246     curparams = &lorendparams;
247     twolevels = bcmp(&lorendparams, &hirendparams, sizeof(RAYPARAMS));
248     }
249    
250    
251     void
252     setmove(om, ms) /* assign a move object from spec. */
253     struct ObjMove *om;
254     char *ms;
255     {
256     char parname[128];
257     char *cp;
258    
259     ms = nextword(parname, sizeof(parname), ms);
260     if (!parname[0])
261     goto badspec;
262     for (cp = parname; *cp; cp++)
263     if (isspace(*cp))
264     *cp = '_';
265     for (om->parent = (om - obj_move); om->parent--; )
266     if (!strcmp(parname, obj_move[om->parent].name))
267     break;
268     if (om->parent < 0 &&
269     strcmp(parname, ".") && strcmp(parname, VOIDID)) {
270     sprintf(errmsg, "undefined parent object '%s'", parname);
271     error(USER, errmsg);
272     }
273     ms = nextword(om->name, sizeof(om->name), ms);
274     if (!om->name[0])
275     goto badspec;
276     for (cp = om->name; *cp; cp++)
277     if (isspace(*cp))
278     *cp = '_';
279     ms = nextword(om->xf_file, sizeof(om->xf_file), ms);
280     if (!strcmp(om->xf_file, "."))
281     om->xf_file[0] = '\0';
282     if (!om->xf_file[0]) {
283     om->xfs[0] = '\0';
284     } else if (om->xf_file[0] == '-') {
285     strcpy(om->xfs, om->xf_file);
286     om->xf_file[0] = '\0';
287     }
288     ms = nextword(om->spec, sizeof(om->spec), ms);
289     if (om->spec[0]) {
290     if (!strcmp(om->spec, ".") || !strcmp(om->spec, VOIDID))
291     om->spec[0] = '\0';
292     ms = nextword(om->prio_file, sizeof(om->prio_file), ms);
293     } else
294     om->prio_file[0] = '\0';
295     if (om->prio_file[0]) {
296     if (isflt(om->prio_file)) {
297     om->prio = atof(om->prio_file);
298     om->prio_file[0] = '\0';
299     haveprio |= (om->prio < 0.95 | om->prio > 1.05);
300     } else
301     haveprio = 1;
302     } else
303     om->prio = 1.;
304     om->cfm = -1;
305     return;
306     badspec:
307     error(USER, "bad object specification");
308     }
309    
310    
311     void
312     setrendparams(optf, qval) /* set global rendering parameters */
313     char *optf;
314     char *qval;
315     {
316     char *argv[1024];
317     char **av = argv;
318     int ac, i, rval;
319    
320     av[ac=0] = NULL;
321     /* load options from file, first */
322     if (optf != NULL && *optf) {
323     ac = wordfile(av, optf);
324     if (ac < 0) {
325     sprintf(errmsg, "cannot load options file \"%s\"",
326     optf);
327     error(SYSTEM, errmsg);
328     }
329     }
330     /* then from options string */
331     if (qval != NULL && qval[0] == '-')
332     ac += wordstring(av+ac, qval);
333    
334     /* start with default parameters */
335     ray_defaults(NULL);
336     /* set what we have */
337     for (i = 0; i < ac; i++) {
338     while ((rval = expandarg(&ac, &av, i)) > 0)
339     ;
340     if (rval < 0) {
341     sprintf(errmsg, "cannot expand '%s'", av[i]);
342     error(SYSTEM, errmsg);
343     }
344     if (!strcmp(av[i], "-w")) {
345     nowarn++;
346     continue;
347     }
348     rval = getrenderopt(ac-i, av+i);
349     if (rval >= 0) {
350     i += rval;
351     continue;
352     }
353     sprintf(errmsg, "bad render option at '%s'", av[i]);
354     error(USER, errmsg);
355     }
356     }
357    
358    
359     void
360     getradfile(rfargs) /* run rad and get needed variables */
361     char *rfargs;
362     {
363     static short mvar[] = {OCONV,OCTREEF,RESOLUTION,EXPOSURE,-1};
364     char combuf[256];
365     register int i;
366     register char *cp;
367     char *pippt;
368     /* create rad command */
369     strcpy(lorendoptf, "ranim0.opt");
370     sprintf(combuf,
371     "rad -v 0 -s -e -w %s %s oconv=-f OPTFILE=%s | egrep '^[ \t]*(NOMATCH",
372     rfargs,
373     (vdef(LOWQ) && vval(LOWQ)[0]!='-') ? vval(LOWQ) : "",
374     lorendoptf);
375     cp = combuf;
376     while (*cp) {
377     if (*cp == '|') pippt = cp;
378     cp++;
379     } /* match unset variables */
380     for (i = 0; mvar[i] >= 0; i++)
381     if (!vdef(mvar[i])) {
382     *cp++ = '|';
383     strcpy(cp, vnam(mvar[i]));
384     while (*cp) cp++;
385     pippt = NULL;
386     }
387     if (pippt != NULL)
388     strcpy(pippt, "> /dev/null"); /* nothing to match */
389     else {
390     strcpy(cp, ")[ \t]*=' > ranimove.var");
391     cp += 11; /* point to file name */
392     }
393     system(combuf); /* ignore exit code */
394     if (pippt == NULL) { /* load variables and remove file */
395     loadvars(cp);
396     unlink(cp);
397     }
398     if (!vdef(HIGHQ) || vval(HIGHQ)[0]=='-') {
399     strcpy(hirendoptf, lorendoptf);
400     return;
401     }
402     /* get high quality options */
403     strcpy(hirendoptf, "ranim1.opt");
404     sprintf(combuf, "rad -v 0 -s -w %s %s OPTFILE=%s",
405     rfargs, vval(HIGHQ), hirendoptf);
406     system(combuf);
407     }
408    
409    
410     void
411     animate() /* run through animation */
412     {
413     int rpass;
414    
415     if (fbeg > 1) /* synchronize transforms */
416     getoctspec(fbeg-1);
417    
418     for (fcur = fbeg; fcur <= fend; fcur++) {
419     if (!silent)
420     printf("Frame %d:\n", fcur);
421     /* base rendering */
422     init_frame();
423     /* refinement */
424     for (rpass = 0; refine_frame(rpass); rpass++)
425     ;
426     /* final filter pass */
427     filter_frame();
428     /* output frame */
429     send_frame();
430     }
431     /* free resources */
432     free_frame();
433     if (nprocs > 1)
434     ray_pdone(1);
435     else
436     ray_done(1);
437     getview(0);
438     getexp(0);
439     }
440    
441    
442     VIEW *
443     getview(n) /* get view number n */
444     int n;
445     {
446     static FILE *viewfp = NULL; /* view file pointer */
447     static int viewnum = 0; /* current view number */
448     static VIEW curview = STDVIEW; /* current view */
449     char linebuf[256];
450    
451     if (n == 0) { /* signal to close file and clean up */
452     if (viewfp != NULL) {
453     fclose(viewfp);
454     viewfp = NULL;
455     viewnum = 0;
456     copystruct(&curview, &stdview);
457     }
458     return(NULL);
459     }
460     if (viewfp == NULL) { /* open file */
461     if ((viewfp = fopen(vval(VIEWFILE), "r")) == NULL) {
462     perror(vval(VIEWFILE));
463     quit(1);
464     }
465     } else if (n > 0 && n < viewnum) { /* rewind file */
466     if (viewnum == 1 && feof(viewfp))
467     return(&curview); /* just one view */
468     if (fseek(viewfp, 0L, 0) == EOF) {
469     perror(vval(VIEWFILE));
470     quit(1);
471     }
472     copystruct(&curview, &stdview);
473     viewnum = 0;
474     }
475     if (n < 0) { /* get next view */
476     register int c = getc(viewfp);
477     if (c == EOF)
478     return(NULL); /* that's it */
479     ungetc(c, viewfp);
480     n = viewnum + 1;
481     }
482     while (n > viewnum) { /* scan to desired view */
483     if (fgets(linebuf, sizeof(linebuf), viewfp) == NULL)
484     return(viewnum==1 ? &curview : (VIEW *)NULL);
485     if (isview(linebuf) && sscanview(&curview, linebuf) > 0)
486     viewnum++;
487     }
488     return(&curview); /* return it */
489     }
490    
491    
492     int
493     countviews() /* count views in view file */
494     {
495     int n;
496    
497     if (getview(n=1) == NULL)
498     return(0);
499     while (getview(-1) != NULL)
500     n++;
501     return(n);
502     }
503    
504    
505     char *
506     getexp(n) /* get exposure for nth frame */
507     int n;
508     {
509     extern char *fskip();
510     static char expval[32];
511     static FILE *expfp = NULL;
512     static int curfrm = 0;
513     register char *cp;
514    
515     if (n == 0) { /* signal to close file */
516     if (expfp != NULL) {
517     fclose(expfp);
518     expfp = NULL;
519     }
520     return(NULL);
521     }
522     if (!vdef(EXPOSURE)) /* no setting (auto) */
523     return(NULL);
524     if (isflt(vval(EXPOSURE))) /* always the same */
525     return(vval(EXPOSURE));
526     if (expfp == NULL) { /* open exposure file */
527     if ((expfp = fopen(vval(EXPOSURE), "r")) == NULL) {
528     sprintf(errmsg, "cannot open exposure file \"%s\"",
529     vval(EXPOSURE));
530     error(SYSTEM, errmsg);
531     }
532     curfrm = 0;
533     }
534     if (curfrm > n) { /* rewind if necessary */
535     rewind(expfp);
536     curfrm = 0;
537     }
538     while (n > curfrm) { /* read to line */
539     if (fgets(expval, sizeof(expval), expfp) == NULL) {
540     sprintf(errmsg, "%s: too few exposures",
541     vval(EXPOSURE));
542     error(USER, errmsg);
543     }
544     if (strlen(expval) == sizeof(expval)-1)
545     goto formerr;
546     curfrm++;
547     }
548     cp = fskip(expval); /* check format */
549     if (cp != NULL)
550     while (isspace(*cp))
551     *cp++ = '\0';
552     if (cp == NULL || *cp)
553     goto formerr;
554     return(expval); /* return value */
555     formerr:
556     sprintf(errmsg, "%s: exposure format error on line %d",
557     vval(EXPOSURE), curfrm);
558     error(USER, errmsg);
559     }
560    
561    
562     double
563     expspec_val(s) /* get exposure value from spec. */
564     char *s;
565     {
566     double expval;
567    
568     if (s == NULL || !*s)
569     return(1.0);
570    
571     expval = atof(s);
572     if ((s[0] == '+' | s[0] == '-'))
573     return(pow(2.0, expval));
574     return(expval);
575     }
576    
577    
578     char *
579     getoctspec(n) /* get octree for the given frame */
580     int n;
581     {
582     static char combuf[1024];
583     int cfm = 0;
584     int uses_inline;
585     FILE *fp;
586     int i;
587     /* is octree static? */
588     if (!vdef(MOVE))
589     return(vval(OCTREEF));
590     /* done already */
591     if (n == cfm)
592     return(combuf);
593     /* else create object file */
594     strcpy(objtmpf, "movinobj.rad");
595     fp = fopen(objtmpf, "w");
596     if (fp == NULL) {
597     sprintf(errmsg, "cannot write to moving objects file '%s'",
598     objtmpf);
599     error(SYSTEM, errmsg);
600     }
601     uses_inline = 0;
602     for (i = 0; i < vdef(MOVE); i++) {
603     int inlc = (obj_move[i].spec[0] == '!');
604     if (!obj_move[i].spec[0])
605     continue;
606     if (inlc)
607     fprintf(fp, "%s %d \\\n\t| xform",
608     obj_move[i].spec, n);
609     else
610     fputs("!xform", fp);
611     fprintf(fp, " -n %s", getobjname(&obj_move[i]));
612     fputs(getxf(&obj_move[i], n), fp);
613     if (!inlc)
614     fprintf(fp, " %s\n", obj_move[i].spec);
615     else
616     fputc('\n', fp);
617     uses_inline |= inlc;
618     }
619     if (fclose(fp) == EOF)
620     error(SYSTEM, "error writing moving objects file");
621     if (uses_inline)
622     sprintf(combuf, "!oconv %s -f -i '%s' %s",
623     vdef(OCONV) ? vval(OCONV) : "",
624     vval(OCTREEF), objtmpf);
625     else
626     sprintf(combuf, "!xform -f %s | oconv -f -i '%s' -",
627     objtmpf, vval(OCTREEF));
628     return(combuf);
629     }
630    
631    
632     char *
633     getobjname(om) /* get fully qualified object name */
634     register struct ObjMove *om;
635     {
636     static char objName[512];
637     register char *cp = objName;
638    
639     strcpy(cp, om->name);
640     while (om->parent >= 0) {
641     while (*cp) cp++;
642     *cp++ = '@';
643     om = &obj_move[om->parent];
644     strcpy(cp, om->name);
645     }
646     return(objName);
647     }
648    
649    
650     char *
651     getxf(om, n) /* get total transform for object */
652     register struct ObjMove *om;
653     int n;
654     {
655     static char xfsbuf[4096];
656     char *xfp;
657     int framestep = 0;
658     XF oxf;
659     FILE *fp;
660     char abuf[512];
661     char *av[64];
662     int ac;
663     int i;
664     register char *cp;
665     /* get parent transform, first */
666     if (om->parent >= 0)
667     xfp = getxf(&obj_move[om->parent], n);
668     else
669     *(xfp = xfsbuf + sizeof(xfsbuf)-1) = '\0';
670     /* get transform spec. & priority */
671     if (om->cfm != n) {
672     if (om->xf_file[0]) {
673     fp = fopen(om->xf_file, "r");
674     if (fp == NULL) {
675     sprintf(errmsg,
676     "cannot open transform file '%s'",
677     om->xf_file);
678     error(SYSTEM, errmsg);
679     }
680     for (i = 0; i < n; i++)
681     if (fgetline(om->xfs, sizeof(om->xfs), fp)
682     == NULL) {
683     sprintf(errmsg,
684     "too few transforms in file '%s'",
685     om->xf_file);
686     error(USER, errmsg);
687     }
688     fclose(fp);
689     }
690     strcpy(cp=abuf, om->xfs);
691     ac = 0;
692     for ( ; ; ) {
693     while (isspace(*cp))
694     *cp++ = '\0';
695     if (!*cp)
696     break;
697     av[ac++] = cp;
698     while (*++cp && !isspace(*cp))
699     ;
700     }
701     av[ac] = NULL;
702     if (xf(&oxf, ac, av) != ac ||
703     fabs(oxf.sca) <= FTINY) {
704     sprintf(errmsg, "bad transform args: %s",
705     om->xfs);
706     error(USER, errmsg);
707     }
708     copymat4(om->xfm, oxf.xfm);
709     if (om->prio_file[0]) {
710     fp = fopen(om->prio_file, "r");
711     if (fp == NULL) {
712     sprintf(errmsg,
713     "cannot open priority file '%s'",
714     om->prio_file);
715     error(SYSTEM, errmsg);
716     }
717     for (i = 0; i < n; i++)
718     if (fgets(abuf, sizeof(abuf), fp)
719     == NULL) {
720     sprintf(errmsg,
721     "too few priorities in file '%s'",
722     om->prio_file);
723     error(USER, errmsg);
724     }
725     fclose(fp);
726     cp = fskip(abuf);
727     if (cp != NULL)
728     while (isspace(*cp))
729     *cp++ = '\0';
730     if (cp == NULL || *cp) {
731     sprintf(errmsg,
732     "priority '%s' in file '%s' not a number",
733     abuf, om->prio_file);
734     error(USER, errmsg);
735     }
736     om->prio = atof(abuf);
737     }
738     framestep = (n == om->cfm + 1);
739     om->cfm = n;
740     }
741     /* prepend to parent transform */
742     if (om->xfs[0]) {
743     i = strlen(om->xfs);
744     if (xfp - i <= xfsbuf)
745     error(INTERNAL, "transform too long in getxf");
746     cp = om->xfs + i;
747     while (i--)
748     *--xfp = *--cp;
749     *--xfp = ' ';
750     }
751     if (framestep)
752     copymat4(oxf.xfm, om->cxfm);
753     if (om->parent >= 0) {
754     multmat4(om->cxfm, om->xfm, obj_move[om->parent].cxfm);
755     om->cprio = obj_move[om->parent].cprio * om->prio;
756     } else {
757     copymat4(om->cxfm, om->xfm);
758     om->cprio = om->prio;
759     }
760     /* XXX bxfm relies on call order */
761     if (framestep)
762     if (invmat4(om->bxfm, om->cxfm))
763     multmat4(om->bxfm, om->bxfm, oxf.xfm);
764     else
765     setident4(om->bxfm);
766     /* all done */
767     return(xfp);
768     }
769    
770    
771     int
772     getmove(obj) /* find matching move object */
773     OBJECT obj;
774     {
775     static int lasti;
776     static OBJECT lasto = OVOID;
777     char *onm, *objnm;
778     int len, len2;
779     register int i;
780    
781     if (obj == OVOID)
782     return(-1);
783     if (obj == lasto)
784     return(lasti);
785     /* look for matching object */
786     onm = objptr(obj)->oname;
787     for (i = vdef(MOVE); i--; ) {
788     objnm = obj_move[i].name;
789     len = strlen(objnm);
790     if (!strncmp(onm, objnm, len)) {
791     if ((obj_move[i].parent < 0 & onm[len] == '.'))
792     break;
793     objnm = getobjname(&obj_move[i]) + len;
794     len2 = strlen(objnm);
795     if (!strncmp(onm+len, objnm, len2) && onm[len+len2] == '.')
796     break;
797     }
798     }
799     lasto = obj; /* cache what we found */
800     return(lasti = i);
801     }
802    
803    
804     double
805     obj_prio(obj) /* return priority for object */
806     OBJECT obj;
807     {
808     int moi;
809    
810     if (obj == OVOID || (moi = getmove(obj)) < 0)
811     return(1.0);
812     return(obj_move[moi].cprio);
813     }
814    
815    
816     double
817     getTime() /* get current time (CPU or real) */
818     {
819     struct timeval time_now;
820     /* return CPU time if one process */
821     if (nprocs == 1)
822     return((double)clock()*(1.0/(double)CLOCKS_PER_SEC));
823     /* otherwise, return wall time */
824     gettimeofday(&time_now, NULL);
825     return((double)time_now.tv_sec + 1e-6*(double)time_now.tv_usec);
826     }