Annotation of OpenXM_contrib2/asir2000/io/ox.c, Revision 1.10
1.5 noro 1: /*
2: * Copyright (c) 1994-2000 FUJITSU LABORATORIES LIMITED
3: * All rights reserved.
4: *
5: * FUJITSU LABORATORIES LIMITED ("FLL") hereby grants you a limited,
6: * non-exclusive and royalty-free license to use, copy, modify and
7: * redistribute, solely for non-commercial and non-profit purposes, the
8: * computer program, "Risa/Asir" ("SOFTWARE"), subject to the terms and
9: * conditions of this Agreement. For the avoidance of doubt, you acquire
10: * only a limited right to use the SOFTWARE hereunder, and FLL or any
11: * third party developer retains all rights, including but not limited to
12: * copyrights, in and to the SOFTWARE.
13: *
14: * (1) FLL does not grant you a license in any way for commercial
15: * purposes. You may use the SOFTWARE only for non-commercial and
16: * non-profit purposes only, such as academic, research and internal
17: * business use.
18: * (2) The SOFTWARE is protected by the Copyright Law of Japan and
19: * international copyright treaties. If you make copies of the SOFTWARE,
20: * with or without modification, as permitted hereunder, you shall affix
21: * to all such copies of the SOFTWARE the above copyright notice.
22: * (3) An explicit reference to this SOFTWARE and its copyright owner
23: * shall be made on your publication or presentation in any form of the
24: * results obtained by use of the SOFTWARE.
25: * (4) In the event that you modify the SOFTWARE, you shall notify FLL by
1.6 noro 26: * e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification
1.5 noro 27: * for such modification or the source code of the modified part of the
28: * SOFTWARE.
29: *
30: * THE SOFTWARE IS PROVIDED AS IS WITHOUT ANY WARRANTY OF ANY KIND. FLL
31: * MAKES ABSOLUTELY NO WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY, AND
32: * EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS
33: * FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT OF THIRD PARTIES'
34: * RIGHTS. NO FLL DEALER, AGENT, EMPLOYEES IS AUTHORIZED TO MAKE ANY
35: * MODIFICATIONS, EXTENSIONS, OR ADDITIONS TO THIS WARRANTY.
36: * UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, TORT, CONTRACT,
37: * OR OTHERWISE, SHALL FLL BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
38: * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL
39: * DAMAGES OF ANY CHARACTER, INCLUDING, WITHOUT LIMITATION, DAMAGES
40: * ARISING OUT OF OR RELATING TO THE SOFTWARE OR THIS AGREEMENT, DAMAGES
41: * FOR LOSS OF GOODWILL, WORK STOPPAGE, OR LOSS OF DATA, OR FOR ANY
42: * DAMAGES, EVEN IF FLL SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF
43: * SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. EVEN IF A PART
44: * OF THE SOFTWARE HAS BEEN DEVELOPED BY A THIRD PARTY, THE THIRD PARTY
45: * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,
46: * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.
1.10 ! noro 47: * $OpenXM: OpenXM_contrib2/asir2000/io/ox.c,v 1.9 2000/11/07 06:35:38 noro Exp $
1.5 noro 48: */
1.1 noro 49: #include "ca.h"
50: #include "parse.h"
1.3 noro 51: #include "signal.h"
1.1 noro 52: #include "wsio.h"
53: #include "ox.h"
54:
55: #define ISIZ sizeof(int)
56:
57: void ox_flush_stream(),ox_write_int(),ox_write_cmo();
58: void ox_read_int(),ox_read_cmo();
59: void mclist_to_mc();
60: void ox_read_local();
61:
62: extern Obj VOIDobj;
63:
64: extern int ox_need_conv;
65: extern int ox_usr1_sent, ox_int_received, critical_when_signal;
66: unsigned int ox_serial;
67: int ox_flushing;
68: int ox_batch;
69: int ox_check=1;
1.2 noro 70: int ox_exchange_mathcap=1;
1.1 noro 71: jmp_buf ox_env;
72:
73: MATHCAP my_mathcap;
74:
75: struct oxcap {
76: unsigned int ox;
77: int ncap;
78: int *cap;
79: };
80:
81: struct mathcap {
82: LIST mc;
83: unsigned int version;
84: char *servername;
85: int nsmcap;
86: unsigned int *smcap;
87: int noxcap;
88: struct oxcap *oxcap;
89: };
90:
91: struct oxcap *my_oxcap;
92:
93: static struct mathcap my_mc;
94: static struct mathcap *remote_mc;
95: static int remote_mc_len;
96:
1.9 noro 97: #if defined(VISUAL)
98: /* XXX : mainly used in engine2000/io.c, but declared here */
99: HANDLE hStreamNotify,hStreamNotify_Ack;
100:
101: void cleanup_events()
102: {
103: /* ox_watch_stream may be waiting for hStreamNotify_Ack to be set */
104:
105: ResetEvent(hStreamNotify);
106: SetEvent(hStreamNotify_Ack);
107: }
108: #endif
109:
1.1 noro 110: void ox_resetenv(s)
111: char *s;
112: {
1.9 noro 113: #if defined(VISUAL)
114: cleanup_events();
115: #endif
1.1 noro 116: fprintf(stderr,"%s\n",s);
117: longjmp(ox_env,1);
118: }
119:
120: static int available_cmo[] = {
121: CMO_NULL, CMO_INT32, CMO_DATUM, CMO_STRING, CMO_MATHCAP,
122: CMO_ERROR, CMO_ERROR2, CMO_LIST, CMO_MONOMIAL32,
123: CMO_ZZ, CMO_QQ, CMO_ZERO,
124: CMO_DMS_GENERIC, CMO_DMS_OF_N_VARIABLES,
125: CMO_RING_BY_NAME, CMO_DISTRIBUTED_POLYNOMIAL,
126: CMO_RECURSIVE_POLYNOMIAL, CMO_UNIVARIATE_POLYNOMIAL,
127: CMO_INDETERMINATE,
128: 0
129: };
130:
131: static int available_sm[] = {
132: SM_dupErrors, SM_getsp, SM_popSerializedLocalObject,
1.7 noro 133: SM_popCMO, SM_popString, SM_pushCMOtag, SM_setName,
1.1 noro 134: SM_evalName, SM_executeStringByLocalParser,
135: SM_executeStringByLocalParserInBatchMode,
136: SM_executeFunction, SM_shutdown, SM_pops,
137: SM_mathcap, SM_setMathcap, SM_nop,
138: SM_beginBlock, SM_endBlock,
139: 0
140: };
141:
142: /*
143: mathcap =
144: [
145: version list,
146: SMlist,
147: [
148: [OX tag,CMO tag list],
149: [OX tag,CMO tag list],
150: ...
151: ]
152: ]
153: */
154:
155: void create_my_mathcap(char *system)
156: {
157: NODE n,n0;
158: int i,k;
159: STRING str;
160: LIST sname,smlist,oxlist,cmolist,asirlist,oxtag,oxasir,r;
161: USINT tag,t,t1;
162:
163: if ( my_mathcap )
164: return;
165: /* version */
166: MKSTR(str,system);
167: MKUSINT(t,OX_VERSION);
168: n0 = mknode(2,t,str); MKLIST(sname,n0);
169:
170: /* cmo tag */
171: for ( n0 = 0, i = 0; k = available_sm[i]; i++ ) {
172: NEXTNODE(n0,n); MKUSINT(t,k); BDY(n) = (pointer)t;
173: }
174: NEXT(n) = 0; MKLIST(smlist,n0);
175:
176: /* creation of [OX_DATA,CMO list] */
177: /* ox tag */
178: MKUSINT(tag,OX_DATA);
179: /* cmo tag */
180: for ( n0 = 0, i = 0; k = available_cmo[i]; i++ ) {
181: NEXTNODE(n0,n); MKUSINT(t,k); BDY(n) = (pointer)t;
182: }
183: NEXT(n) = 0; MKLIST(cmolist,n0);
184: /* [ox tag, cmo list] */
185: n0 = mknode(2,tag,cmolist);
186: MKLIST(oxlist,n0);
187:
188: /* creation of [OX_LOCAL_OBJECT_ASIR,ASIR tag] */
189: /* ox tag */
190: MKUSINT(tag,OX_LOCAL_OBJECT_ASIR);
191: /* local tag */
192: MKUSINT(t,ASIR_VL);
193: MKUSINT(t1,ASIR_OBJ);
194: n0 = mknode(2,t,t1); MKLIST(cmolist,n0);
195: /* [ox tag, local list] */
196: n0 = mknode(2,tag,cmolist);
197: MKLIST(asirlist,n0);
198:
199: /* [oxlist,asirlist] */
200: n0 = mknode(2,oxlist,asirlist); MKLIST(oxasir,n0);
201:
202: /* [version,sm,oxasir] */
203: n0 = mknode(3,sname,smlist,oxasir); MKLIST(r,n0);
204:
205: MKMATHCAP(my_mathcap,r);
206: mclist_to_mc(r,&my_mc);
207: my_oxcap = my_mc.oxcap;
208: }
209:
210: void store_remote_mathcap(int s,MATHCAP mc)
211: {
212: if ( !remote_mc ) {
213: remote_mc_len = 16;
214: remote_mc = (struct mathcap *)
215: CALLOC(remote_mc_len,sizeof(struct mathcap));
216: }
217: if ( s >= remote_mc_len ) {
218: remote_mc_len *= 2;
219: remote_mc = (struct mathcap *)REALLOC(remote_mc,
220: remote_mc_len*sizeof(struct mathcap));
221: }
222: mclist_to_mc(BDY(mc),&remote_mc[s]);
223: }
224:
225: /*
226: mathcap =
227: [
228: version list,
229: SMlist,
230: [
231: [OX tag,CMO tag list],
232: [OX tag,CMO tag list],
233: ...
234: ]
235: ]
236:
237: ===>
238:
239: mathcap
240: | version | &servername | nsmcap | &smcap | noxcap | &oxcap |
241: smcap
242: | SM_xxx | SM_yyy | ... |
243: oxcap
244: | oxcap[0] | oxcap[1] | ... |
245: oxcap[i]
246: | ox | ncap | &cap |
247: cap
248: | CMO_xxx | CMO_yyy | ... |
249: */
250:
251: void mclist_to_mc(LIST mclist,struct mathcap *mc)
252: {
253: int id,l,i,j;
254: NODE n,t,oxcmo,ox,cap;
255: int *ptr;
256:
257: /*
258: [
259: [ version,servername ]
260: [sm1,sm2,...],
261: [
262: [o1,[n11,n12,...]],
263: [o2,[n21,n22,...]],
264: ...
265: ]
266: ]
267: */
268: n = BDY(mclist);
269: mc->mc = mclist;
270: mc->version = BDY((USINT)BDY(BDY((LIST)BDY(n))));
271: mc->servername = BDY((STRING)BDY(NEXT(BDY((LIST)BDY(n)))));
272:
273: /* smcap */
274: n = NEXT(n);
275: t = BDY((LIST)BDY(n));
276: mc->nsmcap = length(t);
277: mc->smcap = (int *)MALLOC_ATOMIC(mc->nsmcap*sizeof(int));
278: for ( j = 0, ptr = mc->smcap; j < mc->nsmcap; j++, t = NEXT(t) )
279: ptr[j] = BDY((USINT)BDY(t));
280:
281: n = NEXT(n);
282: n = BDY((LIST)BDY(n));
283: /* n -> BDY([[OX1,CMOlist1], [OX2,CMOlist2], ...]) */
284: mc->noxcap = length(n);
285: mc->oxcap = (struct oxcap *)MALLOC(mc->noxcap*sizeof(struct oxcap));
286: for ( j = 0; j < mc->noxcap; j++, n = NEXT(n) ) {
287: oxcmo = BDY((LIST)BDY(n));
288: /* oxcmo = BDY([OXj,CMOlistj]) */
289: mc->oxcap[j].ox = BDY((USINT)BDY(oxcmo));
290: cap = BDY((LIST)BDY(NEXT(oxcmo)));
291: /* cap ->BDY(CMOlistj) */
292: l = length(cap);
293: mc->oxcap[j].ncap = l;
294: mc->oxcap[j].cap = (unsigned int *)CALLOC(l+1,sizeof(unsigned int));
295: for ( t = cap, ptr = mc->oxcap[j].cap, i = 0; i < l; t = NEXT(t), i++ )
296: ptr[i] = BDY((USINT)BDY(t));
297: }
298: }
299:
300: int check_sm_by_mc(s,smtag)
301: int s;
302: unsigned int smtag;
303: {
304: struct mathcap *rmc;
305: int nsmcap,i;
306: unsigned int *smcap;
307:
308: /* XXX : return 1 if remote_mc is not available. */
309: if ( !remote_mc )
310: return 1;
311: rmc = &remote_mc[s];
312: nsmcap = rmc->nsmcap;
313: smcap = rmc->smcap;
314: if ( !smcap )
315: return 1;
316: for ( i = 0; i < nsmcap; i++ )
317: if ( smcap[i] == smtag )
318: break;
319: if ( i == nsmcap )
320: return 0;
321: else
322: return 1;
323: }
324:
325: int check_by_mc(s,oxtag,cmotag)
326: int s;
327: unsigned int oxtag,cmotag;
328: {
329: struct mathcap *rmc;
330: int noxcap,ncap,i,j;
331: struct oxcap *oxcap;
332: unsigned int *cap;
333:
334: /* XXX : return 1 if remote_mc is not available. */
335: if ( !remote_mc )
336: return 1;
337: rmc = &remote_mc[s];
338: noxcap = rmc->noxcap;
339: oxcap = rmc->oxcap;
340: if ( !oxcap )
341: return 1;
342: for ( i = 0; i < noxcap; i++ )
343: if ( oxcap[i].ox == oxtag )
344: break;
345: if ( i == noxcap )
346: return 0;
347: ncap = oxcap[i].ncap;
348: cap = oxcap[i].cap;
349: for ( j = 0; j < ncap; j++ )
350: if ( cap[j] == cmotag )
351: break;
352: if ( j == ncap )
353: return 0;
354: else
355: return 1;
356: }
357:
358: void begin_critical() {
359: critical_when_signal = 1;
360: }
361:
362: void end_critical() {
363: critical_when_signal = 0;
364: if ( ox_usr1_sent ) {
365: ox_usr1_sent = 0; ox_usr1_handler();
366: }
367: if ( ox_int_received ) {
368: ox_int_received = 0; int_handler(SIGINT);
369: }
370: }
371:
372: void ox_usr1_handler(sig)
373: int sig;
374: {
375: extern jmp_buf env;
376: unsigned int cmd;
377:
378: #if !defined(VISUAL)
379: signal(SIGUSR1,ox_usr1_handler);
380: #endif
381: if ( critical_when_signal ) {
382: fprintf(stderr,"usr1 : critical\n");
383: ox_usr1_sent = 1;
384: } else {
385: ox_flushing = 1;
386: ox_resetenv("usr1 : return to toplevel by SIGUSR1");
387: }
388: }
389:
390: void clear_readbuffer()
391: {
392: char c;
393: fd_set r,w,e;
394: struct timeval interval;
395: int n,sock;
396:
397: #if defined(linux)
398: iofp[0].in->_IO_read_ptr = iofp[0].in->_IO_read_end;
399: #elif defined(__FreeBSD__)
400: fpurge(iofp[0].in);
401: #endif
402: /*
403: sock = fileno(iofp[0].in);
404: interval.tv_sec = (int)0;
405: interval.tv_usec = (int)0;
406:
407: FD_ZERO(&r); FD_ZERO(&w); FD_ZERO(&e);
408: FD_SET(sock,&r);
409: while ( 1 ) {
410: n = select(FD_SETSIZE,&r,&w,&e,&interval);
411: if ( !n )
412: break;
413: read(sock,&c,1);
414: }
415: */
416: }
417:
418: #if MPI
419: int ox_data_is_available(int s)
420: {
421: return 1;
422: }
423:
424: void wait_for_data(int s)
425: {
426: return;
427: }
428: #else
429: int ox_data_is_available(int s)
430: {
431: return FP_DATA_IS_AVAILABLE(iofp[s].in);
432: }
433:
434: void wait_for_data(int s)
435: {
436: fd_set r;
437: int sock;
438:
439: if ( !FP_DATA_IS_AVAILABLE(iofp[s].in) ) {
440: #if defined(VISUAL)
441: sock = iofp[s].in->fildes;
442: FD_ZERO(&r);
443: FD_SET(sock,&r);
444: select(0,&r,NULL,NULL,NULL);
445: #else
446: sock = fileno(iofp[s].in);
447: FD_ZERO(&r);
448: FD_SET(sock,&r);
449: select(FD_SETSIZE,&r,NULL,NULL,NULL);
450: #endif
451: }
452: }
453: #endif
454:
455: void ox_send_data(int s,pointer p)
456: {
1.8 noro 457: ERR err;
458:
459: if ( ox_check && !ox_check_cmo(s,(Obj)p) ) {
460: create_error(&err,ox_serial,"ox_send_data : Mathcap violation");
461: p = (pointer)err;
462: }
1.1 noro 463: begin_critical();
464: ox_write_int(s,OX_DATA);
465: ox_write_int(s,ox_serial++);
466: ox_write_cmo(s,p);
467: ox_flush_stream(s);
468: end_critical();
469: }
470:
471: void ox_send_cmd(int s,int id)
472: {
473: if ( ox_check && !check_sm_by_mc(s,id) )
474: error("ox_send_cmd : Mathcap violation");
475: begin_critical();
476: ox_write_int(s,OX_COMMAND);
477: ox_write_int(s,ox_serial++);
478: ox_write_int(s,id);
479: ox_flush_stream(s);
480: end_critical();
481: }
482:
483: void ox_send_sync(int s)
484: {
485: begin_critical();
486: ox_write_int(s,OX_SYNC_BALL);
487: ox_write_int(s,ox_serial++);
488: ox_flush_stream(s);
489: end_critical();
490: }
491:
492: void ox_send_local_data(int s,Obj p)
493: {
494: begin_critical();
495: ox_write_int(s,OX_LOCAL_OBJECT_ASIR);
496: ox_write_int(s,ox_serial++);
497: ox_write_int(s,ASIR_OBJ);
498: saveobj(iofp[s].out,p);
499: ox_flush_stream(s);
500: end_critical();
501: }
502:
503: void ox_send_local_ring(int s,VL vl)
504: {
505: begin_critical();
506: ox_write_int(s,OX_LOCAL_OBJECT_ASIR);
507: ox_write_int(s,ox_serial++);
508: ox_write_int(s,ASIR_VL);
509: savevl(iofp[s].out,vl);
510: ox_flush_stream(s);
511: end_critical();
512: }
513:
514: unsigned int ox_recv(int s, int *id, pointer *p)
515: {
516: unsigned int cmd,serial;
517: USINT ui;
518:
519: wait_for_data(s);
520: begin_critical();
521: ox_read_int(s,id);
522: ox_read_int(s,&serial);
523: switch ( *id ) {
524: case OX_COMMAND:
525: ox_read_int(s,&cmd);
526: MKUSINT(ui,cmd);
527: *p = (pointer)ui;
528: break;
529: case OX_DATA:
530: ox_read_cmo(s,p);
531: break;
532: case OX_LOCAL_OBJECT_ASIR:
533: ox_read_local(s,p);
534: break;
535: default:
536: *p = 0;
537: break;
538: }
539: end_critical();
540: return serial;
541: }
542:
543: void ox_get_result(s,rp)
544: int s;
545: Obj *rp;
546: {
547: int id;
548: Obj obj,r;
549: int level;
550:
551: level = 0;
552: r = 0;
553: do {
554: ox_recv(s,&id,(pointer *)&obj);
555: if ( id == OX_COMMAND ) {
556: switch ( ((USINT)obj)->body ) {
557: case SM_beginBlock:
558: level++;
559: break;
560: case SM_endBlock:
561: level--;
562: }
563: } else
564: r = obj;
565: } while ( level );
566: *rp = r;
567: }
568:
569: void ox_read_int(int s, int *n)
570: {
571: ox_need_conv = iofp[s].conv;
572: read_int(iofp[s].in,n);
573: }
574:
575: void ox_read_cmo(int s, Obj *rp)
576: {
577: ox_need_conv = iofp[s].conv;
578: read_cmo(iofp[s].in,rp);
579: }
580:
581: void ox_read_local(int s, Obj *rp)
582: {
583: int id;
584:
585: ox_need_conv = iofp[s].conv;
586: read_int(iofp[s].in,&id);
587: switch ( id ) {
588: case ASIR_VL:
589: loadvl(iofp[s].in);
590: *rp = VOIDobj;
591: break;
592: case ASIR_OBJ:
593: loadobj(iofp[s].in,rp);
594: break;
595: default:
596: error("ox_read_local : unsupported id");
597: break;
598: }
599: }
600:
601: void ox_write_int(int s, int n)
602: {
603: ox_need_conv = iofp[s].conv;
604: write_int(iofp[s].out,&n);
605: }
606:
607: void ox_write_cmo(int s, Obj obj)
608: {
609: ox_need_conv = iofp[s].conv;
610: write_cmo(iofp[s].out,obj);
611: }
612:
613: int ox_check_cmo(int s, Obj obj)
614: {
615: NODE m;
616:
617: if ( !obj )
618: return 1;
619: switch ( OID(obj) ) {
620: case O_MATHCAP: case O_STR: case O_ERR: case O_USINT: case O_VOID:
1.10 ! noro 621: case O_BYTEARRAY:
1.1 noro 622: return 1;
623: case O_P:
624: if ( !check_by_mc(s,OX_DATA,CMO_RECURSIVE_POLYNOMIAL) )
625: return 0;
626: else
627: return ox_check_cmo_p(s,(P)obj);
628: case O_R:
629: if ( !check_by_mc(s,OX_DATA,CMO_RATIONAL) )
630: return 0;
631: else if ( !check_by_mc(s,OX_DATA,CMO_RECURSIVE_POLYNOMIAL) )
632: return 0;
633: else
634: return ox_check_cmo_p(s,NM((R)obj)) && ox_check_cmo_p(s,DN((R)obj));
635: case O_DP:
636: return ox_check_cmo_dp(s,(DP)obj);
637: case O_N:
1.4 noro 638: switch ( NID((Num)obj) ) {
639: case N_Q:
640: if ( INT((Q)obj) )
641: return check_by_mc(s,OX_DATA,CMO_ZZ);
642: else
643: return check_by_mc(s,OX_DATA,CMO_QQ);
644: case N_R:
645: return 1;
646: default:
647: return 0;
648: }
649: break;
1.1 noro 650: case O_LIST:
651: for ( m = BDY((LIST)obj); m; m = NEXT(m) )
652: if ( !ox_check_cmo(s,(BDY(m))) )
653: return 0;
654: return 1;
655: default:
656: return 0;
657: }
658: }
659:
660: void ox_get_serverinfo(int s, LIST *rp)
661: {
662: if ( remote_mc )
663: *rp = remote_mc[s].mc;
664: else {
665: MKLIST(*rp,0);
666: }
667: }
668:
669: int ox_check_cmo_p(int s, P p)
670: {
671: DCP dc;
672:
673: if ( NUM(p) )
674: return ox_check_cmo(s,(Obj)p);
675: else {
676: for ( dc = DC(p); dc; dc = NEXT(dc) )
677: if ( !ox_check_cmo_p(s,COEF(dc)) )
678: return 0;
679: return 1;
680: }
681: }
682:
683: int ox_check_cmo_dp(int s, DP p)
684: {
685: MP m;
686:
687: for ( m = BDY(p); m; m = NEXT(m) )
688: if ( !ox_check_cmo(s,(Obj)m->c) )
689: return 0;
690: return 1;
691: }
692:
693: void ox_flush_stream(s)
694: int s;
695: {
696: if ( ox_batch )
697: return;
698: #if defined(VISUAL)
699: if ( _fileno(&iofp[s].out->fp) < 0 )
700: cflush(iofp[s].out);
701: else
702: #elif MPI
703: if ( (char)fileno(&iofp[s].out->fp) < 0 )
704: cflush(iofp[s].out);
705: else
706: #endif
707: fflush(iofp[s].out);
708: }
709:
710: void ox_flush_stream_force(s)
711: int s;
712: {
713: #if defined(VISUAL)
714: if ( _fileno(&iofp[s].out->fp) < 0 )
715: cflush(iofp[s].out);
716: else
717: #elif MPI
718: if ( (char)fileno(&iofp[s].out->fp) < 0 )
719: cflush(iofp[s].out);
720: else
721: #endif
722: fflush(iofp[s].out);
723: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>