|
|
1.1 root 1: /* The Plum Hall Validation Suite for C
2: * Unpublished copyright (c) 1986-1991, Chiron Systems Inc and Plum Hall Inc.
3: * VERSION: 4
4: * DATE: 1993-01-01
5: * The "ANSI" mode of this suite corresponds to official ANSI C, X3.159-1989.
6: * As per your license agreement, your distribution is not to be moved or copied outside the Designated Site
7: * without specific permission from Plum Hall Inc.
8: */
9:
10:
11: #include "flags.h"
12: #ifndef SKIP49
13: #define LIB_TEST 1
14: /*
15: * 4.9 - Input / Output <stdio.h>
16: */
17: #include <stdio.h>
18: #include <ctype.h>
19: #include "defs.h"
20: #if ANSI
21: #include <stdarg.h>
22: #include <stddef.h>
23: #define W_BIN "wb"
24: #define R_BIN "rb"
25: #define A_BIN "ab"
26: #define WU_BIN "w+b"
27: #define RU_BIN "r+b"
28: #define AU_BIN "a+b"
29: #define W_BIN_U "wb+"
30: #define R_BIN_U "rb+"
31: #define A_BIN_U "ab+"
32: static void d4_9_6_9(char *, char *, ...);
33: #define L_FirstName L_tmpnam
34: #else
35: #define L_FirstName 256
36: #endif
37: static char FirstName[L_FirstName] = {0};
38: char names[25+1][L_FirstName] = {0};
39: int next_name = 0;
40: char *save_name(p)
41: char *p;
42: {
43: if (next_name < 25)
44: str_cpye(names[next_name++], p);
45: return (p);
46: }
47: #if !ANSI && !V7
48: extern int errno;
49: #endif
50: #if ANSI8703 || V7
51: #include <errno.h>
52: #endif
53: /* if ANSI, but prior to 87/03, errno will be found in <stddef.h> */
54: #if !ANSI
55: #define remove unlink
56: #define rename(old, new) ((link(old, new) == 0 && unlink(old) == 0) ? 0 : -1)
57: #define SEEK_SET 0
58: #define SEEK_CUR 1
59: #define SEEK_END 2
60: #define W_BIN "w"
61: #define R_BIN "r"
62: #define A_BIN "a"
63: #define WU_BIN "w+"
64: #define RU_BIN "r+"
65: #define AU_BIN "a+"
66: #define W_BIN_U "w+"
67: #define R_BIN_U "r+"
68: #define A_BIN_U "a+"
69: #endif
70: static int c; /* for use in various SKIPNULLS */
71: static void d4_9_1();
72: static void d4_9_2();
73: static void d4_9_3();
74: static void d4_9_4();
75: static void d4_9_4_4();
76: static void d4_9_5();
77: static void d4_9_5_3();
78: static void d4_9_6();
79: static void d4_9_7();
80: static void d4_9_7_11();
81: static void d4_9_8();
82: static void d4_9_9();
83: static void d4_9_10();
84: void print(); /* in d49a.c */
85: void scan(); /* in d49a.c */
86:
87: void d4_9()
88: {
89: Filename = "d49.c";
90: d4_9_1();
91: d4_9_2();
92: d4_9_3();
93: d4_9_4();
94: d4_9_5();
95: d4_9_6();
96: d4_9_7();
97: d4_9_8();
98: d4_9_9();
99: d4_9_10();
100: d4_9_4_4(); /* do after all tmpnam calls are completed */
101: }
102: /*
103: * 4.9.1 - Introduction
104: */
105: static void d4_9_1()
106: {
107: #ifndef SKIP491
108: #if ANSI
109:
110: int i, j, k;
111: FILE *files[FOPEN_MAX-3];
112: int open_success = 1;
113:
114: /* check for existence of required macros */
115: i = _IOFBF;
116: j = _IOLBF;
117: k = _IONBF;
118: checkthat(__LINE__, EOF < 0);
119:
120: /* size_t is defined here (and elsewhere) */
121: iequals(__LINE__, sizeof(size_t), sizeof(sizeof(size_t)));
122:
123: #ifndef FILENAME_MAX
124: complain(__LINE__);
125: #endif
126: /* make sure that FOPEN_MAX-3 files can be opened simultaneously ...
127: * the -3 allows for stdin, stdout, and stderr.
128: *
129: * IT HAS BEEN DETERMINED THAT THE STANDARD DOES NOT MANDATE THAT
130: * CALLING tmpfile FOR FOPEN_MAX-3 TIMES MUST SUCCEED.
131: * AN IMPLEMENTATION WHICH FAILS THIS FORM OF THE TEST MAY SUPPLY
132: * AN ALTERNATIVE PROGRAM TO DEMONSTRATE THAT FOPEN_MAX-3 FILES
133: * CAN BE OPENED SUCCESSFULLY.
134: */
135: open_success = 1;
136: for (i = 0; i < FOPEN_MAX-3; ++i)
137: {
138: files[i] = tmpfile();
139: if (files[i] == NULL)
140: {
141: open_success = 0;
142: break;
143: }
144: }
145: checkthat(__LINE__, open_success == 1); /* success at fopen'ing FOPEN_MAX files */
146:
147:
148: /* now clean it up */
149: while (--i >= 0)
150: fclose(files[i]);
151: #endif
152: #endif /* SKIP491 */
153: }
154:
155: /*
156: * 4.9.2 - Streams
157: */
158: static void d4_9_2()
159: {
160: #ifndef SKIP492
161: int i;
162: char to[254], from[254];
163: FILE *fd;
164:
165: save_name(tmpnam(FirstName));
166:
167: /* in text mode, we are guaranteed to get back chars in the
168: * same order as written if they are printable, HT, NL, VT, or FF
169: */
170: fd = fopen(FirstName, "w");
171: for (i = 0; i < 256; ++i)
172: if (isprint(i) || i == '\t' || i == '\v' || i == '\n' || i == '\f')
173: fputc(i, fd);
174: fputc('\n', fd);
175: fclose(fd);
176: fd = fopen(FirstName, "r");
177: for (i = 0; i < 256; ++i)
178: if (isprint(i) || i == '\t' || i == '\v' || i == '\n' || i == '\f')
179: if (!iequals(__LINE__, fgetc(fd), i))
180: break;
181: iequals(__LINE__, fgetc(fd), '\n');
182: iequals(__LINE__, fgetc(fd), EOF);
183: fclose(fd);
184: remove(FirstName);
185:
186: /* in binary mode, the characters must all match */
187: fd = fopen(FirstName, W_BIN);
188: for (i = 0; i < 256; ++i)
189: fputc(i, fd);
190: fclose(fd);
191: fd = fopen(FirstName, R_BIN);
192: for (i = 0; i < 256; ++i)
193: if (!iequals(__LINE__, fgetc(fd), i))
194: break;
195: #define SKIPNULLS(fd, i) \
196: if ((i = fgetc(fd)) == 0) \
197: { complain(- __LINE__); while ((i = fgetc(fd)) == 0) ; }
198: SKIPNULLS(fd, i);
199:
200: iequals(__LINE__, i, EOF);
201:
202: fclose(fd);
203: remove(FirstName);
204:
205: /* make sure that a text mode file can support a line == 254 chars */
206: fd = fopen(FirstName, "w");
207: for (i = 0; i < 253; ++i)
208: to[i] = "0123456789"[i % 10];
209: to[253] = '\n';
210: fwrite(to, 254, 1, fd);
211: fwrite(" \n", 2, 1, fd); /* ANSI8612 write whitespace before newline */
212: fclose(fd);
213: fd = fopen(FirstName, "r");
214: fread(from, 254, 1, fd);
215: for (i = 0; i < 253; ++i)
216: if (!iequals(__LINE__, from[i], "0123456789"[i % 10]))
217: break;
218: iequals(__LINE__, from[253], '\n');
219: fread(from, 2, 1, fd); /* ANSI8612 read the whitespace */
220: from[2] = '\0';
221: if (str_cmp(from, " \n") != 0) /* 4.9.2 P2s1 */
222: {
223: complain(- __LINE__); /* whether the blank reads back is implem-def */
224: iequals(__LINE__, from[0], '\n'); /* but if it does not, the line must be just newline */
225: }
226: fclose(fd);
227: remove(FirstName);
228:
229: checkthat(__LINE__, BUFSIZ >= 256);
230: #endif /* SKIP492 */
231: }
232:
233: /*
234: * 4.9.3 - Files
235: */
236: static void d4_9_3()
237: {
238: #ifndef SKIP493
239: char *name;
240: FILE *fd;
241:
242: /* just check existence */
243: FILE *f1 = stdin;
244: FILE *f2 = stdout;
245: FILE *f3 = stderr;
246:
247: #if ANSI
248: #if ANSI8712
249: checkthat(__LINE__, FOPEN_MAX >= 8);
250: #else
251: checkthat(__LINE__, OPEN_MAX >= 8);
252: #endif
253:
254: /* whether a file of 0 length actually exists is implementation defined */
255: name = save_name(tmpnam(NULL));
256: fd = fopen(name, "w");
257: fclose(fd);
258: fd = fopen(name, "r");
259: checkthat(- __LINE__, fd != NULL);
260: fclose(fd);
261: remove(name);
262: #endif
263: #endif /* SKIP493 */
264: }
265:
266: /*
267: * 4.9.4 Operations on files
268: */
269: static void d4_9_4()
270: {
271: #ifndef SKIP494
272: FILE *f;
273: char *old, *new, *tmp;
274: #if ANSI
275: char name[L_tmpnam], buf1[L_tmpnam], buf2[L_tmpnam], buf3[L_tmpnam];
276: #else
277: static char name[] = "dXXXXXX";
278: extern char *mktemp();
279: #endif
280:
281: /* 4.9.4.1 - remove */
282: /* remove of non-existent file returns non-zero */
283: inotequals(__LINE__, remove(save_name(tmpnam(NULL))), 0);
284:
285: /* successful remove returns 0 */
286: f = fopen(new=save_name(tmpnam(NULL)), "w");
287: fputc('a', f); fputc('\n', f);
288: fclose(f);
289: iequals(__LINE__, remove(new), 0);
290:
291: /* 4.9.4.2 The rename function */
292: #if ANSI
293: old = save_name(tmpnam(buf1));
294: new = save_name(tmpnam(buf2));
295: tmp = save_name(tmpnam(buf3));
296: #else
297: old = mktemp("aXXXXXX");
298: new = mktemp("bXXXXXX");
299: tmp = mktemp("cXXXXXX");
300: #endif
301: /* make a file, write to it, rename it, check it, clean up */
302: checkthat(__LINE__, (f = fopen(old, "w")) != NULL);
303: fputc('x', f); fputc('\n', f);
304: fclose(f);
305: iequals(__LINE__, rename(old, new), 0);
306: checkthat(__LINE__, (f = fopen(new, "r")) != NULL);
307: iequals(__LINE__, fgetc(f), 'x');
308: iequals(__LINE__, fgetc(f), '\n');
309: fclose(f);
310:
311: /* make sure that the old file is effectively removed */
312: checkthat(__LINE__, (f = fopen(old, "r")) == NULL);
313:
314: /* attempt to rename non-existent file should fail and return non 0 */
315: inotequals(__LINE__, rename(tmp, old), 0);
316:
317: /* if the new file exists, the behavior is implementation defined */
318: checkthat(__LINE__, (f = fopen(tmp, "w")) != NULL);
319: fputc('x', f); fputc('\n', f);
320: fclose(f);
321: inotequals(- __LINE__, rename(new, tmp), 0);
322:
323: /* clean up */
324: remove(new);
325: remove(tmp);
326: #if ANSI
327: /* 4.9.4.3 The tmpfile function */
328: /* temporary file creation */
329: f = tmpfile();
330: fputc('y', f);
331: fputc('\n', f);
332: iequals(__LINE__, ferror(f), 0);
333: fseek(f, 0L, SEEK_SET);
334: iequals(__LINE__, fgetc(f), 'y');
335: fclose(f);
336: #endif
337: /* 4.9.4.4 The tmpnam function */
338: #if ANSI
339: checkthat(__LINE__, TMP_MAX >= 25);
340: old = save_name(tmpnam(buf1));
341: aequals(__LINE__, old, buf1);
342: #else
343: old = mktemp(name);
344: aequals(__LINE__, old, name);
345: #endif
346: /* old and new above should have created unique names */
347: checkthat(__LINE__, str_cmp(old, new) != 0);
348: #endif /* SKIP494 */
349: }
350:
351: /*
352: * 4.9.5 - File access functions
353: */
354: char details[BUFSIZ] = {0};
355: static void d4_9_5()
356: {
357: #ifndef SKIP495
358: FILE *f, *g;
359: #if ANSI
360: char buf1[L_tmpnam];
361: char buf2[L_tmpnam];
362: char *afile = save_name(tmpnam(buf1));
363: char *bfile = save_name(tmpnam(buf2));
364: #else
365: char *afile = mktemp("aXXXXXX");
366: char *bfile = mktemp("bXXXXXX");
367: #endif
368:
369: /* 4.9.5.1 The fclose function */
370: f = fopen(afile, "w");
371: fputc('z', f);
372: fputc('\n', f);
373: iequals(__LINE__, fclose(f), 0);
374:
375: /* 4.9.5.2 The fflush function */
376: /* fflush undoes the effects of an ungetc ... tested in 4.9.7.11 */
377: #if ANSI8804
378: iequals(__LINE__, fflush(NULL), 0); /* flush all output streams */
379: #endif /* ANSI8804 */
380: /* make sure the previous write worked OK */
381: f = fopen(afile, "r");
382: iequals(__LINE__, fgetc(f), 'z');
383: iequals(__LINE__, fgetc(f), '\n');
384: fgetc(f);
385: inotequals(__LINE__, feof(f), 0);
386: fclose(f);
387: iequals(__LINE__, remove(afile), 0);
388:
389: /* 4.9.5.3 The fopen function */
390: d4_9_5_3();
391:
392: /* 4.9.5.4 The reopen function */
393: f = fopen(afile, "wb");
394: fputc('a', f);
395: fclose(f);
396: f = fopen(bfile, "w+b");
397: fputc('b', f);
398: rewind(f);
399: checkthat(__LINE__, (f = freopen(afile, "rb", f)) != NULL);
400:
401: /* should now be reading from afile, not bfile */
402: iequals(__LINE__, fgetc(f), 'a');
403: fclose(f);
404:
405: /* do reopens to change modes */
406: checkthat(__LINE__, (f = fopen(afile, "rb")) != NULL);
407: iequals(__LINE__, fgetc(f), 'a');
408: checkthat(__LINE__, (f = freopen(afile, "wb", f)) != NULL);
409: iequals(__LINE__, fputc('c', f), 'c');
410: checkthat(__LINE__, (f = freopen(afile, "rb", f)) != NULL);
411: iequals(__LINE__, fgetc(f), 'c');
412: checkthat(__LINE__, (f = freopen(afile, "ab", f)) != NULL);
413: iequals(__LINE__, fputc('d', f), 'd');
414: if (checkthat(__LINE__, (f = freopen(afile, "r+b", f)) != NULL))
415: {
416: iequals(__LINE__, fgetc(f), 'c');
417: SKIPNULLS(f, c); iequals(__LINE__, c, 'd');
418: rewind(f);
419: iequals(__LINE__, fputc('e', f), 'e');
420: iequals(__LINE__, fputc('f', f), 'f');
421: checkthat(__LINE__, (f = freopen(afile, "rb", f)) != NULL);
422: iequals(__LINE__, fgetc(f), 'e');
423: iequals(__LINE__, fgetc(f), 'f');
424: SKIPNULLS(f, c);
425: if (c == 'd')
426: SKIPNULLS(f, c);
427: iequals(__LINE__, c, EOF);
428: checkthat(__LINE__, (f = freopen(afile, "w+b", f)) != NULL);
429: iequals(__LINE__, fputc('g', f), 'g');
430: rewind(f);
431: iequals(__LINE__, fgetc(f), 'g');
432: SKIPNULLS(f, c);
433: if (c == 'f')
434: SKIPNULLS(f, c);
435: iequals(__LINE__, c, EOF);
436: }
437: fclose(f);
438: /* get NULL pointer on failure ? */
439: remove(bfile);
440: f = fopen(afile, "rb");
441: if (freopen(bfile, "rb", f) != NULL)
442: {
443: complain(__LINE__); /* freopen should have failed: no bfile */
444: fclose(f);
445: }
446: /* 4.9.5.5 The setbuf function */
447: /* we have already checked for existence ... about all we can do is
448: * call it and make sure that it doesn't crash the program.
449: */
450: f = fopen(afile, "rb");
451: setbuf(f, NULL);
452: setbuf(f, details);
453: /* 4.9.5.6 The setvbuf function */
454: #if ANSI
455: /* not much that can be done except check for 0/nonzero return */
456: /* ANSI8809 - re-affirms that setvbuf is allowed to be "unable to perform" */
457: iequals( - __LINE__, setvbuf(f, details, _IOFBF, BUFSIZ/2), 0);
458: iequals( - __LINE__, setvbuf(f, details, _IOLBF, BUFSIZ/2), 0);
459: iequals( - __LINE__, setvbuf(f, details, _IONBF, BUFSIZ/2), 0);
460: iequals( - __LINE__, setvbuf(f, NULL, _IOFBF, BUFSIZ/2), 0);
461: iequals( - __LINE__, setvbuf(f, NULL, _IOLBF, BUFSIZ/2), 0);
462: iequals( - __LINE__, setvbuf(f, NULL, _IONBF, BUFSIZ/2), 0);
463:
464: /* force an illegal size and mode */
465: checkthat( - __LINE__, setvbuf(f, NULL, _IOFBF, -1) != 0);
466: checkthat(__LINE__, setvbuf(f, NULL, _IOFBF+_IOLBF+_IONBF, 0) != 0);
467: #endif
468:
469: fclose(f);
470: remove(afile);
471: #endif /* SKIP495 */
472: }
473:
474: /*
475: * 4.9.5.3 - test all of the file open modes.
476: */
477: static void d4_9_5_3()
478: {
479: #ifndef SKIP4953 /* note: if SKIP495 is defined, 4953 isn't called */
480: FILE *f;
481: #if ANSI
482: fpos_t pos;
483: char *afile = save_name(tmpnam(NULL));
484: #else
485: char *afile = mktemp("aXXXXXX");
486: #endif
487: int c;
488:
489: /* open with "r" and non-existent file fails */
490: aequals(__LINE__, fopen(afile, "r"), NULL);
491:
492: /* TEXT MODE
493: * open(write), write a char, close.
494: * open(read), read a char, check value, close.
495: * open(append), seek, 0, write a char,
496: * open(read), check that write was to end of file
497: */
498: checkthat(__LINE__, (f = fopen(afile, "w")) != NULL);
499:
500: /* make sure that ferror and feof are 0 at this point */
501: iequals(__LINE__, ferror(f), 0);
502: iequals(__LINE__, feof(f), 0);
503:
504: fputc('d', f); fputc('\n', f);
505: fclose(f);
506:
507: checkthat(__LINE__, (f = fopen(afile, "r")) != NULL);
508: iequals(__LINE__, fgetc(f), 'd');
509: fclose(f);
510:
511: checkthat(__LINE__, (f = fopen(afile, "a")) != NULL);
512: fseek(f, 0L, SEEK_SET);
513: fputc('e', f); fputc('\n', f);
514: fclose(f);
515: checkthat(__LINE__, (f = fopen(afile, "r")) != NULL);
516: iequals(__LINE__, fgetc(f), 'd');
517: iequals(__LINE__, fgetc(f), '\n');
518: iequals(__LINE__, fgetc(f), 'e');
519: iequals(__LINE__, fgetc(f), '\n');
520: fclose(f);
521: remove(afile);
522:
523: /* BINARY MODE
524: * same sequence, but with binary mode opens
525: */
526: checkthat(__LINE__, (f = fopen(afile, W_BIN)) != NULL);
527: fputc(1, f);
528: fclose(f);
529:
530: checkthat(__LINE__, (f = fopen(afile, R_BIN)) != NULL);
531: iequals(__LINE__, fgetc(f), 1);
532: fclose(f);
533:
534: checkthat(__LINE__, (f = fopen(afile, A_BIN)) != NULL);
535: fseek(f, 0L, SEEK_SET);
536: fputc(2, f);
537: fclose(f);
538: {
539: char c;
540:
541: checkthat(__LINE__, (f = fopen(afile, R_BIN)) != NULL);
542: iequals(__LINE__, fgetc(f), 1);
543: SKIPNULLS(f, c);
544: iequals(__LINE__, c, 2);
545: fclose(f);
546: remove(afile);
547: }
548:
549: /* UPDATE TEXT
550: * open(write update), write, seek 0, read, check, close.
551: * open(read update), read, check, seek 0, write, seek 0, check, close.
552: * open(append update), seek 0, write, seek 0, read, check, close
553: * open(read), read, check.
554: */
555: checkthat(__LINE__, (f = fopen(afile, "w+")) != NULL);
556: fputc('f', f); fputc('\n', f);
557: fseek(f, 0L, SEEK_SET);
558: iequals(__LINE__, fgetc(f), 'f');
559: fclose(f);
560: checkthat(__LINE__, (f = fopen(afile, "r+")) != NULL);
561: iequals(__LINE__, fgetc(f), 'f');
562: fseek(f, 0L, SEEK_SET);
563: fputc('g', f);
564: fseek(f, 0L, SEEK_SET);
565: iequals(__LINE__, fgetc(f), 'g');
566: fclose(f);
567: checkthat(__LINE__, (f = fopen(afile, "a+")) != NULL);
568: fseek(f, 0L, SEEK_SET);
569: fputc('h', f);
570: fputc('\n', f);
571: fseek(f, 0L, SEEK_SET);
572: iequals(__LINE__, fgetc(f), 'g');
573: iequals(__LINE__, fgetc(f), '\n');
574: SKIPNULLS(f, c); iequals(__LINE__, c, 'h'); /* open might be binary */
575: iequals(__LINE__, fgetc(f), '\n');
576: fclose(f);
577: remove(afile);
578:
579: /* UPDATE BINARY (X+B form)
580: * open(write update), write, seek 0, read, check, close.
581: * open(read update), read, check, seek 0, write, seek 0, check, close.
582: * open(append update), seek 0, write, seek -2, read, check, close
583: * open(read), read, check.
584: */
585: checkthat(__LINE__, (f = fopen(afile, WU_BIN)) != NULL);
586: fputc('f', f);
587: fseek(f, 0L, SEEK_SET);
588: /* we wrote 'f' ... go back to zero and check that it is there */
589: iequals(__LINE__, fgetc(f), 'f');
590: fclose(f);
591: checkthat(__LINE__, (f = fopen(afile, RU_BIN)) != NULL);
592: /* close and reopen (for read-write) ... check that it is 'f' */
593: iequals(__LINE__, fgetc(f), 'f');
594: fseek(f, 0L, SEEK_SET);
595: fputc('g', f);
596: fseek(f, 0L, SEEK_SET);
597:
598: /* we wrote over it with a 'g' ... check that out */
599: iequals(__LINE__, fgetc(f), 'g');
600: fclose(f);
601: checkthat(__LINE__, (f = fopen(afile, AU_BIN)) != NULL);
602: fseek(f, 0L, SEEK_SET);
603: fputc('h', f);
604: fseek(f, -2L, SEEK_CUR);
605: iequals( - __LINE__, fgetc(f), 'g');
606: iequals(__LINE__, fgetc(f), 'h');
607: fclose(f);
608: checkthat(__LINE__, (f = fopen(afile, R_BIN)) != NULL);
609: /* by now the file should have a 'g' and an 'h' in it */
610: iequals(__LINE__, fgetc(f), 'g');
611: SKIPNULLS(f, c); iequals(__LINE__, c, 'h');
612: fclose(f);
613:
614: /* In update mode, there must be a fseek,rewind,fpos, or EOF between
615: * input and output, or an fflush between output and input.
616: * Diagrams use _ for file position, N for possible nul-padding,
617: * and n for new-line
618: */
619: checkthat(__LINE__, (f = fopen(afile, W_BIN)) != NULL);
620: fputc('g', f); /* g_ */
621: fputc('\n', f); /* g n_ */
622: fclose(f); /* g n N */
623:
624: checkthat(__LINE__, (f = fopen(afile, R_BIN_U)) != NULL);
625: iequals(__LINE__, fgetc(f), 'g'); /* g_n N */
626: fseek(f, 0L, SEEK_SET); /* _g n N */
627: iequals(__LINE__, fgetc(f), 'g'); /* g_n N */
628: iequals(__LINE__, fgetc(f), '\n'); /* g n_N */
629: SKIPNULLS(f, c); iequals(__LINE__, c, EOF); /* g n N_ */
630: fseek(f, 0L, SEEK_SET); /* _g n N */
631: fputc('i', f); /* i_n N */
632:
633: /* now make sure that these work */
634: fseek(f, 0L, SEEK_SET); /* _i n N */
635: iequals(__LINE__, fgetc(f), 'i'); /* i_n N */
636: fseek(f, 0L, SEEK_SET); /* _i n N */
637: fputc('j', f); /* j_n N */
638: fseek(f, 0L, SEEK_SET); /* _j n N */
639: iequals(__LINE__, fgetc(f), 'j'); /* j_n N */
640: iequals(__LINE__, fgetc(f), '\n'); /* j n_N */
641: SKIPNULLS(f, c); iequals(__LINE__, c, EOF); /* j n N_ */
642: fseek(f, 0L, SEEK_CUR); /* j n N_*/
643: fputc('z', f); /* j n N z_ */
644: fseek(f, 0L, SEEK_SET); /* _j n N z N */
645: iequals(__LINE__, fgetc(f), 'j'); /* j_n N z N */
646: rewind(f); /* _j n N z N */
647: fputc('k', f); /* k_n N z N */
648: rewind(f); /* _k n N z N */
649: iequals(__LINE__, fgetc(f), 'k'); /* k_n N z N */
650: iequals(__LINE__, fgetc(f), '\n'); /* k n_N z N */
651: SKIPNULLS(f, c); iequals(__LINE__, c, 'z'); /* k n N z_N */
652: SKIPNULLS(f, c); iequals(__LINE__, c, EOF); /* k n N z N_ */
653: #if ANSI
654: fseek(f, 0L, SEEK_SET); /* _k n N z N */
655: iequals(__LINE__, fgetc(f), 'k'); /* k_n N z N */
656: fseek(f, 0L, SEEK_CUR); /* allow writing */ /* k_n N z N */
657: fputc('l', f); /* k l_N z N */
658: fputc('\n', f); /* k l n_N z N */
659: rewind(f); /* _k l n N z N */
660: iequals(__LINE__, fgetc(f), 'k'); /* k_l n N z N */
661: iequals(__LINE__, fgetc(f), 'l'); /* k l_n N z N */
662: iequals(__LINE__, fgetc(f), '\n'); /* k l n_N z N */
663:
664: fseek(f, 0L, SEEK_SET); /* _k l n N z N */
665: fgetpos(f, &pos); /* _k l n N z N */
666: iequals(__LINE__, fgetc(f), 'k'); /* k_l n N z N */
667: fsetpos(f, &pos); /* _k l n N z N */
668: fputc('m', f); /* m_l n N z N */
669: fsetpos(f, &pos); /* _m l n N z N */
670: iequals(__LINE__, fgetc(f), 'm'); /* m_l n N z N */
671: iequals(__LINE__, fgetc(f), 'l'); /* m l_n N z N */
672: iequals(__LINE__, fgetc(f), '\n'); /* m l n_N z N */
673:
674: #endif
675: fclose(f); /* m l n N z N */
676: remove(afile); /* removed */
677:
678: /* UPDATE BINARY (using XB+ form)
679: * open(write update), write, seek 0, read, check, close.
680: * open(read update), read, check, seek 0, write, seek -1, check, close.
681: * open(append update), seek 0, write, seek -1, read, check, close
682: * open(read), read, check.
683: */
684: checkthat(__LINE__, (f = fopen(afile, W_BIN_U)) != NULL);
685: fputc('f', f); /* f_ */
686: fseek(f, 0L, SEEK_SET); /* _f */
687: /* we wrote 'f' ... go back to zero and check that it is there */
688: iequals(__LINE__, fgetc(f), 'f'); /* f_ */
689: fclose(f); /* f N */
690: checkthat(__LINE__, (f = fopen(afile, R_BIN_U)) != NULL);
691: /* close and reopen (for read-write) */ /* _f N */
692: iequals(__LINE__, fgetc(f), 'f'); /* f_N */
693: fseek(f, 0L, SEEK_SET); /* _f N */
694: fputc('g', f); /* g_N */
695: fseek(f, -1L, SEEK_CUR); /* _g N */
696: iequals(__LINE__, fgetc(f), 'g'); /* g_N */
697: /* we wrote over it with a 'g' */
698: fclose(f); /* g N */
699: checkthat(__LINE__, (f = fopen(afile, A_BIN_U)) != NULL);
700: fseek(f, 0L, SEEK_SET); /* _g N */
701: fputc('h', f); /* appended */ /* _g N h */
702: fseek(f, 1L, SEEK_SET); /* g_N h */
703: SKIPNULLS(f, c); /* g N h_ */
704: iequals(__LINE__, c, 'h'); /* g N h_ */
705: fclose(f); /* g N h N */
706: checkthat(__LINE__, (f = fopen(afile, R_BIN)) != NULL);
707: /* should have a 'g' and an 'h' */ /* _g N h N */
708: iequals(__LINE__, fgetc(f), 'g'); /* g_N h N */
709: SKIPNULLS(f, c); /* g N h_N */
710: iequals(__LINE__, c, 'h'); /* g N h_N */
711: fclose(f); /* g N h N */
712:
713: remove(afile); /* removed */
714: #endif /* SKIP4953 */
715: }
716:
717: /*
718: * 4.9.6 Formatted input/output functions
719: */
720: static void d4_9_6()
721: {
722: #ifndef SKIP496
723: int i, j;
724: char buff[20];
725: char *p;
726:
727: /* 4.9.6.1 The fprintf function */
728: /* 4.9.6.2 The fscanf function */
729: /* 4.9.6.3 The printf function */
730: /* 4.9.6.4 The scanf function */
731: /* 4.9.6.5 The sprintf function */
732: /* make sure that excess args are evaluated */
733: sprintf(buff, "%d", 3, i = 17);
734: stequals(__LINE__, buff, "3");
735: iequals(__LINE__, i, 17);
736:
737: /* returns number of characters transmitted */
738: iequals(__LINE__, sprintf(buff, "%d", 17), 2);
739: iequals(__LINE__, sprintf(buff, "%d %d", 17, 123), 6);
740: iequals(__LINE__, sprintf(buff, "%s", ""), 0);
741: iequals(__LINE__, sprintf(buff, "%%"), 1);
742:
743: /* now check all of the formatting primitives */
744: print();
745: Filename = "d49.c";
746:
747: /* 4.9.6.6 The sscanf function */
748: scan();
749: Filename = "d49.c";
750: /* return number of items converted */
751: iequals(__LINE__, sscanf("def", "abc", &p), 0);
752: iequals(__LINE__, sscanf("7", "%d", &i, &j), 1);
753: iequals(__LINE__, sscanf("7 8", "%d", &i, &j), 1);
754: iequals(__LINE__, sscanf("7 8", "%d %d", &i, &j), 2);
755:
756: /* 4.9.6.7 The vfprintf function */
757: /* 4.9.6.8 The vprintf function */
758: /* 4.9.6.9 The vsprintf function */
759: #if ANSI
760: d4_9_6_9(buff, "%s %d %s", "string1", 23, "string2");
761: stequals(__LINE__, buff, "string1 23 string2");
762: #endif
763: #endif /* SKIP496 */
764: }
765:
766: /*
767: * 4.9.6.9 - check out the varargs form of formatting. */
768: #if ANSI
769: #if NEW_STYLE_FN_DEF
770: static void d4_9_6_9(char *buff, char *fmt, ...)
771: #else
772: static void d4_9_6_9(buff, fmt)
773: char *buff;
774: char *fmt;
775: #endif
776: {
777: va_list args;
778:
779: va_start(args, fmt);
780: vsprintf(buff, fmt, args);
781: va_end(args);
782: }
783: #endif
784:
785: /*
786: * 4.9.7 Character input/output
787: */
788: static void d4_9_7()
789: {
790: #ifndef SKIP497
791: FILE *f;
792: char buff[65];
793: int c, i;
794: #if ANSI
795: char *afile = save_name(tmpnam(NULL));
796: #else
797: char *afile = mktemp("aXXXXXX");
798: #endif
799:
800: /* 4.9.7.1 The fgetc function */
801: /* 4.9.7.2 The fgets function */
802: /* 4.9.7.3 The fputc function */
803: /* 4.9.7.4 The fputs function */
804:
805: /* fgetc and fputc */
806: f = fopen(afile, W_BIN);
807: iequals(__LINE__, fputc(255, f), 255);
808: iequals(__LINE__, fputc(0, f), 0);
809: fclose(f);
810: f = fopen(afile, R_BIN);
811: /* make sure that there is no sign extension */
812: iequals(__LINE__, fgetc(f), 255);
813: iequals(__LINE__, fgetc(f), 0);
814: SKIPNULLS(f, c);
815: iequals(__LINE__, c, EOF);
816: fclose(f);
817: remove(afile);
818:
819: /* fputs and fgets */
820: f = fopen(afile, "w");
821: checkthat(__LINE__, fputs("string1\nstring2\nstring3\n", f) >= 0); /* ANSI8709: weakened requirement */
822: fclose(f);
823: f = fopen(afile, "r");
824: aequals(__LINE__, fgets(buff, 40, f), buff);
825: iequals(__LINE__, str_cmp(buff, "string1\n"), 0);
826: fgets(buff, 3, f);
827: iequals(__LINE__, str_cmp(buff, "st"), 0);
828: fgets(buff, 40, f);
829: iequals(__LINE__, str_cmp(buff, "ring2\n"), 0);
830: fgets(buff, 40, f);
831: iequals(__LINE__, str_cmp(buff, "string3\n"), 0);
832: aequals(__LINE__, fgets(buff, 40, f), NULL);
833: /* buffer remains unchanged upon end of file */
834: iequals(__LINE__, str_cmp(buff, "string3\n"), 0);
835: fclose(f);
836:
837: /* error returns NULL */
838: f = fopen(afile, "w");
839: aequals(__LINE__, fgets(buff, 40, f), NULL);
840: /* error returns non zero */
841: f = freopen(afile, "r", f);
842: /* inotequals( - __LINE__, fputs(buff, f), 0); */
843: fclose(f);
844: remove(afile);
845:
846: /* 4.9.7.5 The getc function */
847: /* 4.9.7.6 The getchar function */
848: /* 4.9.7.7 The gets function */
849: /* 4.9.7.8 The putc function */
850: /* 4.9.7.9 The putchar function */
851: /* 4.9.7.10 The puts function */
852: /* getc and putc */
853: f = fopen(afile, W_BIN);
854: iequals(__LINE__, putc(255, f), 255);
855: iequals(__LINE__, putc(0, f), 0);
856: fclose(f);
857: f = fopen(afile, R_BIN);
858: /* make sure that there is no sign extension */
859: iequals(__LINE__, getc(f), 255);
860: iequals(__LINE__, getc(f), 0);
861: SKIPNULLS(f, c);
862: iequals(__LINE__, c, EOF);
863: fclose(f); remove(afile);
864: /* getchar, putchar, puts, gets not tested; we don't want to lose stdin and stdout. */
865: /* 4.9.7.11 The ungetc function */
866: f = fopen(afile, "w");
867: iequals(__LINE__, fputc('a', f), 'a');
868: iequals(__LINE__, fputc('z', f), 'z');
869: fclose(f);
870: d4_9_7_11(afile, "r");
871: f = fopen(afile, "w+");
872: iequals(__LINE__, fputc('a', f), 'a');
873: iequals(__LINE__, fputc('z', f), 'z');
874: fclose(f);
875: d4_9_7_11(afile, "r+");remove(afile);
876:
877: f = fopen(afile, W_BIN);
878: iequals(__LINE__, fputc('a', f), 'a');
879: iequals(__LINE__, fputc('z', f), 'z');
880: fclose(f);
881: d4_9_7_11(afile, R_BIN);
882: d4_9_7_11(afile, R_BIN_U);
883: #if ANSI
884: /* it should be possible to do an ungetc on an empty file */
885: f = fopen(afile, W_BIN_U);
886: iequals(__LINE__, ungetc('b', f), 'b');
887: iequals(__LINE__, getc(f), 'b');
888: /* fscanf and ungetc should not get in each others way */
889: rewind(f);
890: fprintf(f, "123abc\n");
891: rewind(f);
892: fscanf(f, "%d", &i);
893: ungetc('x', f);
894: iequals(__LINE__, getc(f), 'x');
895: iequals(__LINE__, getc(f), 'a');
896: fclose(f);
897: #endif
898: remove(afile);
899: #endif /* SKIP497 */
900: }
901:
902: /*
903: * 4.9.7.11 - the ungetc code will get executed for several
904: * different file open modes.
905: */
906: static void d4_9_7_11(afile, mode)
907: char *afile;
908: char *mode;
909: {
910: #ifndef SKIP497_11 /* note: if SKIP497 is defined, 497_11 isn't called */
911: long oldpos;
912: int c;
913: FILE *f;
914: #if ANSI
915: fpos_t pos;
916: #endif
917:
918: f = fopen(afile, mode);
919: #if ANSI
920: fgetpos(f, &pos);
921: #endif
922: iequals(__LINE__, fgetc(f), 'a');
923: iequals(__LINE__, ungetc('b', f), 'b');
924: iequals(__LINE__, getc(f), 'b');
925: iequals(__LINE__, ungetc('c', f), 'c');
926:
927: /* fseek, rewind, and fsetpos lose ungot character */
928: fseek(f, 0L, SEEK_SET);
929: iequals( - __LINE__, getc(f), 'a');
930: iequals(__LINE__, getc(f), 'z');
931: iequals(__LINE__, ungetc('b', f), 'b');
932: rewind(f);
933: iequals(__LINE__, getc(f), 'a');
934: iequals(__LINE__, getc(f), 'z');
935: #if ANSI
936: ungetc('b', f);
937: fsetpos(f, &pos);
938: iequals(__LINE__, getc(f), 'a');
939: iequals(__LINE__, getc(f), 'z');
940: #endif
941:
942: /* the external file remains unchanged */
943: iequals(__LINE__, ungetc('b', f), 'b');
944: fclose(f);
945: f = fopen(afile, mode);
946: iequals(__LINE__, fgetc(f), 'a');
947: iequals(__LINE__, fgetc(f), 'z');
948: SKIPNULLS(f, c);
949: /* record oriented systems might add this newline */
950: if (c == '\n')
951: c = fgetc(f);
952: iequals(__LINE__, c, EOF);
953: fclose(f);
954:
955: /* ungetc of EOF has no effect */
956: f = fopen(afile, mode);
957: iequals(__LINE__, fgetc(f), 'a');
958: iequals(__LINE__, ungetc(EOF, f), EOF);
959: iequals(__LINE__, fgetc(f), 'z');
960: SKIPNULLS(f, c);
961: /* record oriented systems might add this newline */
962: if (c == '\n')
963: c = fgetc(f);
964: iequals(__LINE__, c, EOF);
965: #if ANSI
966: /* a successful ungetc clears the EOF indicator */
967: iequals(__LINE__, ungetc('b', f), 'b');
968: iequals(__LINE__, feof(f), 0);
969: iequals(__LINE__, fgetc(f), 'b');
970: #endif
971: /* after ungetc then read, the file position is restored */
972: oldpos = ftell(f);
973: iequals(__LINE__, ungetc('b', f), 'b');
974: iequals(__LINE__, fgetc(f), 'b');
975: lequals(__LINE__, ftell(f), oldpos);
976:
977: /* if binary, the file position decrements by 1 */
978: if (str_str(mode, "b") != NULL)
979: {
980: oldpos = ftell(f);
981: iequals(__LINE__, ungetc('a', f), 'a');
982: lequals(__LINE__, ftell(f), oldpos - 1L);
983: }
984: #if ANSI
985: /* ANSI requires ability to do an ungetc at the start of a file */
986: rewind(f);
987: iequals(__LINE__, ungetc('b', f), 'b');
988: iequals(__LINE__, fgetc(f), 'b');
989: iequals(__LINE__, fgetc(f), 'a');
990: #endif
991: fclose(f);
992: #endif /* SKIP497_11 */
993: }
994:
995: /*
996: * 4.9.8 - Direct input/output functions
997: */
998: static long array1[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
999: static long array2[11] = {0};
1000: static void d4_9_8()
1001: {
1002: #ifndef SKIP498
1003: FILE *f;
1004: int i;
1005: #if ANSI
1006: char *afile = save_name(tmpnam(NULL));
1007: #else
1008: char *afile = mktemp("aXXXXXX");
1009: #endif
1010: int c;
1011:
1012: /* 4.9.8.1 The fread function */
1013: /* 4.9.8.2 The fwrite function */
1014:
1015: f = fopen(afile, W_BIN);
1016: iequals(__LINE__, fwrite(array1, sizeof(long), 10, f), 10);
1017: fclose(f);
1018: f = fopen(afile, R_BIN);
1019: iequals(__LINE__, fread(array2, sizeof(long), 6, f), 6);
1020:
1021: /* zero size or nelem leaves array unchanged */
1022: iequals(__LINE__, fread(array2, 0, sizeof(long), f), 0);
1023: iequals(__LINE__, fread(array2, 10, 0, f), 0);
1024:
1025: /* incomplete read */
1026: iequals(__LINE__, fread(array2+6, sizeof(long), 4, f), 4);
1027: for (i = 0; i < 10; ++i)
1028: lequals(__LINE__, array2[i], array1[i]);
1029: SKIPNULLS(f, c);
1030:
1031: /* at end of file */
1032: iequals(__LINE__, fread(array2, 10, sizeof(long), f), 0);
1033: fclose(f);
1034: remove(afile);
1035: #endif /* SKIP498 */
1036: }
1037:
1038: /*
1039: * 4.9.9 - Random-access functions
1040: */
1041: static char buffer[] = " this is a test string of no particular significance\n";
1042: static char xchar[] = "abcdefghijklmnopqrstuvwxyz";
1043: static void d4_9_9()
1044: {
1045: #ifndef SKIP499
1046: FILE *f;
1047: int i;
1048: long array[100];
1049: #if ANSI
1050: fpos_t pos[100];
1051: char *afile = save_name(tmpnam(NULL));
1052: #else
1053: char *afile = mktemp("aXXXXXX");
1054: #endif
1055:
1056: /* 4.9.9.1 The fgetpos function */
1057: /* 4.9.9.2 The fseek function */
1058: /* 4.9.9.3 The fsetpos function */
1059: /* 4.9.9.4 The ftell function */
1060:
1061: /*
1062: * create a file with 100 strings, mark the "ftell" position
1063: * of each one, and read them in backwards.
1064: */
1065: f = fopen(afile, "w+");
1066: for (i = 0; i < 100; ++i)
1067: {
1068: array[i] = ftell(f);
1069: buffer[0] = xchar[i%26];
1070: fwrite(buffer, sizeof(buffer), 1, f);
1071: }
1072: for (i = 99; i >= 0; --i)
1073: {
1074: fseek(f, array[i], SEEK_SET);
1075: fread(buffer, sizeof(buffer), 1, f);
1076: iequals(__LINE__, xchar[i%26], buffer[0]);
1077: }
1078: fclose(f); remove(afile);
1079:
1080: /* for binary files, ftell can compute offsets */
1081: f = fopen(afile, WU_BIN);
1082: fwrite(array, sizeof(long), 100, f);
1083: lequals(__LINE__, ftell(f), 100L*sizeof(long));
1084:
1085: fseek(f, 50L, SEEK_SET);
1086: lequals(__LINE__, ftell(f), 50L);
1087: fseek(f, 40L, SEEK_CUR);
1088: lequals(__LINE__, ftell(f), 90L);
1089: fseek(f, -40L, SEEK_END);
1090: lequals( - __LINE__, ftell(f), 100*sizeof(long)-40L); /* "remark" only - could be nul-padded */
1091:
1092: /* fseek clears the end of file indicator */
1093: fseek(f, 0L, SEEK_END);
1094: iequals(__LINE__, fgetc(f), EOF);
1095: fseek(f, 0L, SEEK_END);
1096: iequals(__LINE__, feof(f), 0);
1097:
1098: /* fseek: bad requests return non-zero
1099: * ftell: bad requests return -1L and set errno
1100: */
1101: inotequals(__LINE__, fseek(f, -1L, SEEK_SET), 0);
1102: fclose(f); remove(afile);
1103: errno = 0;
1104:
1105: #if ANSI
1106: lequals(__LINE__, ftell(f), -1L);
1107: inotequals(__LINE__, errno, 0);
1108: #endif
1109:
1110: f = fopen(afile, W_BIN_U);
1111: #if ANSI
1112: /*
1113: * create a file with 100 strings, mark the "getpos" position
1114: * of each one, and read them in backwards.
1115: */
1116: for (i = 0; i < 100; ++i)
1117: {
1118: fgetpos(f, &pos[i]);
1119: buffer[0] = xchar[i%26];
1120: fwrite(buffer, sizeof(buffer), 1, f);
1121: }
1122: for (i = 99; i >= 0; --i)
1123: {
1124: fsetpos(f, &pos[i]);
1125: fread(buffer, sizeof(buffer), 1, f);
1126: iequals(__LINE__, xchar[i%26], buffer[0]);
1127: }
1128:
1129: /* successful return is 0, unsuccessful is non-zero + errno */
1130: iequals(__LINE__, fgetpos(f, &pos[0]), 0);
1131: iequals(__LINE__, fsetpos(f, &pos[0]), 0);
1132: #endif
1133: fputs("a\n", f); /* be sure that following tests work, even for non-ANSI */
1134: fclose(f);
1135:
1136: /* 4.9.9.5 The rewind function */
1137: /* rewind is the same as fseek(f, 0L, SEEK_SET) */
1138: /* in order for ftell(f) to be well-defined, */
1139: /* file f must be binary (and must be created as binary) */
1140: f = fopen(afile, R_BIN);
1141: if (f == NULL)
1142: complain(__LINE__);
1143: else
1144: {
1145: fseek(f, 0L, SEEK_END);
1146: iequals(__LINE__, fgetc(f), EOF);
1147: rewind(f);
1148: lequals(__LINE__, ftell(f), 0L);
1149: fclose(f);
1150: }
1151: remove(afile);
1152: #endif /* SKIP499 */
1153: }
1154:
1155: /*
1156: * 4.9.10 - Error-handling functions
1157: */
1158: static void d4_9_10()
1159: {
1160: #ifndef SKIP49_10
1161: FILE *f;
1162: char * (*fp)();
1163: #if ANSI
1164: char *afile = save_name(tmpnam(NULL));
1165: #else
1166: char *afile = mktemp("aXXXXXX");
1167: extern void perror();
1168: #endif
1169: char c;
1170:
1171: /* 4.9.9.1 The clearerr function */
1172: /* 4.9.9.2 The feof function */
1173:
1174: f = fopen(afile, W_BIN);
1175: fputc('x', f);
1176: fclose(f);
1177: f = fopen(afile, R_BIN);
1178: iequals(__LINE__, feof(f), 0);
1179: fgetc(f);
1180: SKIPNULLS(f, c);
1181: inotequals(__LINE__, feof(f), 0);
1182: clearerr(f);
1183: iequals(__LINE__, feof(f), 0);
1184:
1185: /* 4.9.9.3 The ferror function */
1186: iequals(__LINE__, ferror(f), 0);
1187:
1188: /* There is unfortunately no portable way to force an "I/O error" for testing ferror */
1189:
1190: #if ANSI
1191: /* 4.9.9.4 The perror function */
1192: /* just check for existence */
1193: errno = 0;
1194: perror(NULL);
1195: #endif
1196:
1197: fclose(f);
1198: remove(afile);
1199: #endif /* SKIP49_10 */
1200: }
1201:
1202: /*
1203: * 4.9.4.4 - Now that tmpnam() is no longer needed, verify that
1204: * we can get at least 25 unique names (the min-max for TMP_MAX).
1205: * next_name is how many have been used so far.
1206: */
1207: static void d4_9_4_4()
1208: {
1209: #ifndef SKIP4944
1210: int i, j;
1211:
1212: #if ANSI
1213: for (i = 0; i < next_name; ++i)
1214: for (j = 0; j < i; ++j)
1215: if (str_cmp(names[i], names[j]) == 0)
1216: {
1217: complain(__LINE__);
1218: return;
1219: }
1220: for (i = next_name; i < 25; ++i)
1221: {
1222: if (checkthat(__LINE__, tmpnam(names[i]) != NULL) != 0)
1223: return;
1224: for (j = 0; j < i; ++j)
1225: if (str_cmp(names[i], names[j]) == 0)
1226: {
1227: complain(__LINE__);
1228: return;
1229: }
1230: }
1231: #endif
1232: #endif /* SKIP4944 */
1233: }
1234:
1235: #else /* if SKIP49 */
1236: void d4_9() { pr_skip("d4_9: SKIPPED ENTIRELY\n"); }
1237: #endif
1238:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.