📄 ckuus5.c
字号:
if (*s == '{') kp++; /* Count braces */ if (*s == '}') kp--; if (*s == '(') pp++; /* Count parentheses. */ if (*s == ')') pp--; if (*s == ',' && pp <= 0 && kp <= 0) { macp[maclvl]++; /* Comma not in {} or () */ debug(F110,"next cmd",s,0); kp = pp = 0; /* so we have the next command */ break; }#ifdef COMMENT }#endif /* COMMENT */ } /* Reached end. */ if (*s2 == NUL) { /* If nothing was copied, */ debug(F100,"getncm eom","",0); popclvl(); /* pop command level. */ return(-1); } else { /* otherwise, tack CR onto end */ *s++ = CR; *s = '\0'; if (mecho && pflag) /* If MACRO ECHO ON, echo the cmd */ printf("%s\n",s2); debug(F110,"getncm returns ptr to",s2,0); } return(0);}/* D O M A C -- Define and then execute a macro */intdomac(name, def, flags) char *name, *def; int flags; { int x, m;#ifdef OS2 extern int term_io; int term_io_sav = term_io; term_io = 0; /* Disable Terminal Emulator I/O */#endif /* OS2 */ m = maclvl; /* Current macro stack level */ debug(F101,"domac entry maclvl","",maclvl); x = addmac(name, def); /* Define a new macro */ if (x > -1) { /* If successful, */ dodo(x,NULL,flags); /* start it (increments maclvl). */ while (maclvl > m) { /* Keep going till done with it, */ debug(F101,"domac loop maclvl 1","",maclvl); sstate = (CHAR) parser(1); /* parsing & executing each command, */ debug(F101,"domac loop maclvl 2","",maclvl); if (sstate) proto(); /* including protocol commands. */ } debug(F101,"domac loop exit maclvl","",maclvl); }#ifdef OS2 term_io = term_io_sav;#endif /* OS2 */ return(success);}#endif /* NOSPL *//* G E T N C T Get next command from TAKE (command) file. Call with: s Pointer to buffer to read into n Length of buffer f File descriptor of file to read from flag 0 == keep line terminator on and allow continuation 1 == discard line terminator and don't allow continuation Call with flag == 0 to read a command from a TAKE file; Call with flag != 0 to read a line from a dialing or network directory. In both cases, trailing comments and/or trailing whitespace is/are stripped. If flag == 0, continued lines are combined into one line. A continued line is one that ends in hypen, or any line in a "block", which starts with "{" at the end of a line and ends with a matching "}" at the beginning of a subsequent line; blocks may be nested. Returns: 0 if a string was copied, -1 on EOF, -2 on malloc failure -3 if line is not properly terminated -4 if (possibly continued) line is too long.*/static char * lpx = NULL;static int lpxlen = 0;intgetnct(s,n,f,flag) char *s; int n; FILE *f; int flag; { int i = 0, len = 0, buflen = 0; char c = NUL, cc = NUL, ccl = NUL, ccx = NUL, *s2 = NULL; char *lp = NULL, *lpx = NULL, *lp2 = NULL, *lp3 = NULL, *lastcomma = NULL; int bc = 0; /* Block counter */ s2 = s; /* Remember original pointer */ buflen = n; /* Remember original buffer length */ debug(F101,"getnct","",n); if (n < 0) return(-2); /* Allocate a line buffer only if we don't have one that's big enough */ if (lpx && (n > lpxlen)) { /* Have one already */ free(lpx); /* But it's not big enough */ lpx = NULL; /* Free current one */ lpxlen = 0; } if (!lpx) { /* Get new one */ if (!(lpx = (char *) malloc(n))) { debug(F101,"getnct malloc failure","",0); printf("?Memory allocation failure [getnct]\n"); return(-2); } lpxlen = n; } lp2 = lpx;#define KLUDGE /* See below */#ifdef KLUDGE lp2++;#endif /* KLUDGE */ while (1) { /* Loop to read lines from file */ if (fgets(lp2,n,f) == NULL) { /* Read a line into lp2 */ debug(F100,"getnct fgets EOF","",0); /* EOF */ free(lpx); /* Free temporary storage */ lpx = NULL; *s = NUL; /* Make destination be empty */ return(-1); /* Return failure code */ }#ifndef NODIAL if (flag) /* Count this line */ dirline++; else#endif /* NODIAL */ tfline[tlevel]++; len = strlen(lp2) - 1; /* Position of line terminator */ debug(F111,"getnct fgets ok",lp2,len); if (len == 0 && lp2[0] != '\n') { /* Last line in file has one char */ lp2[++len] = '\n'; /* that is not a newline */ lp2[len] = NUL; } if (len < 0) len = 0; if (techo && pflag) /* If TAKE ECHO ON, */ printf("%3d. %s", /* echo it this line. */#ifndef NODIAL flag ? dirline :#endif /* NODIAL */ tfline[tlevel], lp2 ); lp3 = lp2; /* Working pointer */ i = len; /* Get first nonwhitespace character */ while (i > 0 && *lp3 == SP || *lp3 == HT) { i--; lp3++; } if (i == 0 && bc > 0) /* Blank line in {...} block */ continue; /* Isolate, remove, and check terminator */ c = lp2[len]; /* Value of line terminator */ debug(F101,"getnct terminator","",c); if (c < LF || c > CR) { /* It's not a terminator */ debug(F111,"getnct bad line",lp2,c); if (feof(f) && len > 0 && len < n) { /* Kludge Alert... */ if (!quiet) printf("WARNING: Last line of %s lacks terminator\n", s2 == cmdbuf ? "command file" : "directory file"); c = lp2[++len] = '\n'; /* No big deal - supply one. */ } else { /* Something's wrong, fail. */ free(lpx); lpx = NULL; return(-3); } } /* Trim trailing whitespace */ for (i = len - 1; i > -1 && lp2[i] <= SP; i--) /* Trim */ ; debug(F101,"getnct i","",i); lp2[i+1] = NUL; /* Terminate the string */ debug(F110,"getnct lp2",lp2,0); lp = lp2; /* Make a working pointer */ /* Remove trailing or full-line comment */ while (cc = *lp) { if (cc == ';' || cc == '#') { /* Comment introducer? */ if (lp == lp2) { /* First char on line */ *lp = NUL; break; } else if (*(lp - 1) == SP || *(lp - 1) == HT) { lp--; *lp = NUL; /* Or preceded by whitespace */ break; } } lp++; } if (lp > lp2) lp--; /* Back up over the NUL */ /* Now trim any space that preceded the comment */ while ((*lp == SP || *lp == HT) && lp >= lp2) { *lp = NUL; if (lp <= lp2) break; lp--; } debug(F110,"getnct comment trimmed",lp2,0); len = strlen(lp2); /* Length after trimming */ if (n - len < 2) { /* Check remaining space */ debug(F111,"getnct command too long",s2,buflen); printf("?Line too long, maximum length: %d.\n",buflen); free(lpx); return(-4); } ccl = (len > 0) ? lp2[len-1] : 0; /* Last character in line */ ccx = (len > 1) ? lp2[len-2] : 0; /* Penultimate char in line */#ifdef KLUDGE/* If it is a command and it begins with a token (like ! or .) that is not followed by a space, insert a space now; otherwise cmkey() can get might confused.*/ if (s == s2 && !flag) { char *p = toktab; while (*p) { if (*p == *lp3 && *(p+1) != SP) { *lp3-- = SP; *lp3 = *p; if (lp3 < lp2) { lp2--; len++; } break; } else p++; } }#endif /* KLUDGE */ lp = lp2; while (*s++ = *lp++) /* Copy result to target buffer */ n--; /* accounting for length */ s--; /* Back up over the NUL */ /* Check whether this line is continued */ if (flag) /* No line continuation when flag=1 */ break; /* So break out of read-lines loop */ debug(F000,"getnct first char","",*lp3); debug(F000,"getnct last char","",ccl); debug(F000,"getnct next-to-last char","",ccx); if (bc > 0 && *lp3 == '}') /* First char on line is '}' */ bc--; /* Decrement block counter */ if (bc == 0 && /* Line is continued if bc > 0 */#ifdef COMMENT /* Not supported as of C-Kermit 6.0 */ ccl != CMDQ && /* or line ends with CMDQ */#endif /* COMMENT */ ccl != '-' && /* or line ends with dash */ ccl != '{') /* or line ends with opening brace */ break; /* None of those, we're done. */ if (ccl == '-' || ccl == '{') /* Continuation character */ if (ccx == CMDQ) /* But it's quoted */ break; /* so ignore it */ if (ccl == '{') { /* Last char on line is '{'? */ bc++; /* Count the block opener. */ } else if (ccl == '-' /* Explicit continue? */#ifdef COMMENT/* Not supported as of C-Kermit 6.0. */ || ccl == CMDQ#endif /* COMMENT */ ) { char c, * ss; int state = 0, nn; s--; /* Yes, back up over terminators */ n++; /* and over continuation character */ nn = n; /* Save current count */ ss = s; /* and pointer */ s--; /* Back up over dash */ n++; debug(F110,"XXX lp2 A",s2,0); while (state < 2 && s >= s2) { /* Check for "{,-" */ n++; c = *s--; debug(F000,"XXX c","",c); if (c <= SP) continue; if (c != ',' && c != '{') break; switch (state) { case 0: /* Looking for comma */ if (c == ',') state = 1; break; case 1: /* Looking for left brace */ if (c == '{') { state = 2; s += 2; *s = NUL; bc++; } break; } } if (state != 2) { s = ss; n = nn; } debug(F110,"XXX lp2 B",s2,0); } else { /* None of those but (bc > 0) */ lastcomma = s; *s++ = ','; /* and insert a comma */ n--; } debug(F101,"getnct bc","",bc); debug(F100,"getnct continued","",0); } /* read-lines while loop */ if (lastcomma) *lastcomma = SP; if (!flag) /* Tack line terminator back on */ *s++ = c; *s++ = NUL; /* Terminate the string */ untab(s2); /* Done, convert tabs to spaces */ debug(F110,"getnct return",s2,0); free(lpx); /* Free temporary storage */ return(0); /* Return success */}VOIDshostack() { /* Dump the command stack */ int i; char *p;#ifndef NOSPL for (i = cmdlvl; i > 0; i--) { if (cmdstk[i].src == CMD_TF) { p = tfnam[cmdstk[i].lvl]; if (zfnqfp(p,TMPBUFSIZ,tmpbuf)) p = tmpbuf; printf(" %2d. File : %s (line %d)\n", i, p, tfline[cmdstk[i].lvl] ); } else if (cmdstk[i].src == CMD_MD) { char * m; m = m_arg[cmdstk[i].lvl][0]; /* Name of this macro */ if (i > 0) { /* Special handling for 2-level */ char *s; /* built-in macros... */ s = m_arg[cmdstk[i-1].lvl][0]; /* Name next level up */ if (s && cmdstk[i-1].src == CMD_MD) { if (!strcmp(s,"_forx")) m = "FOR"; else if (!strcmp(s,"_xif")) m = "XIF"; else if (!strcmp(s,"_while")) m = "WHILE"; else if (!strcmp(s,"_switx")) m = "SWITCH"; } } printf(" %2d. Macro : %s\n",i,m); } else { printf(" 00. ERROR : Command source unknown\n"); } }#else for (i = tlevel; i > -1; i--) { p = tfnam[i]; if (zfnqfp(p,TMPBUFSIZ,tmpbuf)) p = tmpbuf; printf(" %2d. File : %s (line %d)\n", i, p, tfline[i] ); }#endif /* NOSPL */ if (i == 0) printf(" %2d. Prompt: (top level)\n",0);}/* P A R S E R -- Top-level interactive command parser. *//* Call with: m = 0 for normal behavior: keep parsing and executing commands until an action command is parsed, then return with a Kermit start-state as the value of this function. m = 1 to parse only one command, can also be used to call parser() recursively. m = 2 to read but do not execute one command. In all cases, parser() returns: 0 if no Kermit protocol action required > 0 with a Kermit protocol start-state. < 0 upon error.*/intparser(m) int m; { int tfcode, xx, yy, zz; /* Workers */ int is_tn = 0;#ifndef NOSPL int inlevel; /* Level we were called at */ extern int askflag;#endif /* NOSPL */ char *cbp; /* Command buffer pointer */#ifdef MAC extern char *lfiles; /* Fake extern cast */#endif /* MAC */#ifndef NOXFER extern int sndcmd, getcmd, interrupted, fatalio, clearrq;#endif /* NOXFER */#ifdef AMIGA reqres(); /* Restore AmigaDOS requestors */#endif /* AMIGA */#ifdef OS2 if (cursor_save > -1) { /* Restore cursor if it was */ cursorena[VCMD] = cursor_save; /* turned off during file transfer */ cursor_save = -1; }#endif /* OS2 */ what = W_COMMAND; /* Now we're parsing commands. */#ifdef IKSDB if (ikdbopen) slotstate(what,"COMMAND PROMPT","",""); /* IKSD database */#endif /* IKSDB */ is_tn = (local && network && ttnproto == NP_TELNET) || (!local && sstelnet); if (!cmdsrc()) /* If at top (interactive) level ... */ concb((char)escape); /* put console in 'cbreak' mode. */#ifdef CK_TMPDIR/* If we were cd'd temporarily to another device or directory ... */ if (f_tmpdir) { int x; x = zchdir((char *) savdir); /* ... restore previous directory */ f_tmpdir = 0; /* and remember we did it. */ debug(F111,"parser tmpdir restoring",savdir,x); }#endif /* CK_TMPDIR */#ifndef NOSPL inlevel = cmdlvl; /* Current macro level */#ifdef DEBUG if (deblog) { debug(F101,"&parser entry maclvl","",maclvl); debug(F101,"&parser entry inlevel","",inlevel); debug(F101,"&parser entry tlevel","",tlevel); debug(F101,"&parser entry cmdlvl","",cmdlvl); debug(F101,"&parser entry m","",m); }#endif /* DEBUG */#endif /* NOSPL */#ifndef NOXFER ftreset(); /* Reset global file-xfer settings */#endif /* NOXFER *//* sstate becomes nonzero when a command has been parsed that requires some action from the protocol module. Any non-protocol actions, such as local
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -