1: #include "../h/rt.h" 2: 3: /* 4: * writes(a,b,...) - write arguments without newline terminator. 5: */ 6: 7: Xwrites(nargs) 8: int nargs; 9: { 10: register int n; 11: char sbuf[MAXSTRING]; 12: struct descrip arg; 13: FILE *f; 14: extern char *alcstr(); 15: 16: f = stdout; 17: arg = nullstr; 18: 19: /* 20: * Loop through the arguments, dereferencing each in turn. 21: */ 22: for (n = 1; n <= nargs; n++) { 23: arg = ARG(n); 24: DeRef(arg) 25: 26: if (!QUAL(arg) && TYPE(arg) == T_FILE) {/* Current argument is a file */ 27: /* 28: * Switch the current file to the file named by the current argument 29: * providing it is a file. arg is made to be a empty string to 30: * avoid a special case. 31: */ 32: if ((BLKLOC(arg)->file.status & FS_WRITE) == 0) 33: runerr(213, &arg); 34: f = BLKLOC(arg)->file.fd; 35: arg = nullstr; 36: } 37: else { /* Current argument is a string */ 38: /* 39: * On first argument, check to be sure that &output is open 40: * for output. 41: */ 42: if (n == 1 && (k_output.status & FS_WRITE) == 0) 43: runerr(213, NULL); 44: /* 45: * Convert the argument to a string, defaulting to a empty string. 46: */ 47: defany(&arg, &nullstr); 48: if (cvstr(&arg, sbuf) == NULL) 49: runerr(109, &arg); 50: /* 51: * Output the string and flush the file. 52: */ 53: putstr(f, STRLOC(arg), STRLEN(arg)); 54: fflush(f); 55: } 56: } 57: /* 58: * If the beginning of the last string output lies in sbuf, 59: * allocate it as a real string. Note that some of the string 60: * conversions don't always leave the converted string at the 61: * start of the conversion buffer, hence the range check. 62: */ 63: if (STRLOC(arg) >= sbuf && STRLOC(arg) < sbuf + MAXSTRING) { 64: sneed(STRLEN(arg)); 65: STRLOC(arg) = alcstr(STRLOC(arg), STRLEN(arg)); 66: } 67: /* 68: * Return the string corresponding to the last argument. 69: */ 70: ARG(0) = arg; 71: } 72: 73: Procblock(writes,-1)