📄 sscanf.c
字号:
#include <limits.h>#include <stdio.h>#include <string.h>#include "script.h"#define inchar() ((c = string[pos++]), \ pos>stringlen ? \ EOF : (++read_in, c))#define conv_error() return(done)#define input_error() return(-1)#define memory_error() return(-1)#define SCALL(x) if(x) return -1;/* Read formatted input from String according to the format string FORMAT, using the argument list in ARG. Return the number of assignments made, or -1 for an input error. */longSscanf(struct Data *scr, uchar *string, uchar *format, long argc, void **param_array, uchar *param_types){ struct Identifier *ident; long stringlen = string?FPL_STRLEN(string):0; /* length of string to parse */ long pos=0; /* current scan point! */ char *f = format; char fc; /* Current character of the format. */ long done = 0; /* Assignments done. */ long read_in = 0; /* Chars read in. */ long c; /* Last char read. */ long do_assign; /* Whether to do an assignment. */ long width; /* Maximum field width. */ /* Type modifiers. */ char is_short, is_long, is_long_double;#ifdef HAVE_LONGLONG /* We use the `L' modifier for `long long int'. */#define is_longlong is_long_double#else#define is_longlong 0#endif /* If a [...] is a [^...]. */ char not_in; /* Base for integral numbers. */ long base; /* Integral holding variables. */ long num; unsigned long unum; /* Workspace. */ char work[200]; char *w; /* Pointer into WORK. */ long param_num = 1; /* start on (0 and 1 is the first strings) 2nd param! */ if (format == NULL) { input_error(); } c = inchar(); /* Run through the format string. */ while (*f != '\0') { fc = *f++; if (fc != '%') { /* Characters other than format specs must just match. */ if (c == EOF) input_error(); if (isspace(fc)) { /* Whitespace characters match any amount of whitespace. */ while (isspace (c)) inchar (); continue; } else if (c == fc) (void) inchar(); else conv_error(); continue; } /* Check for the assignment-suppressant. */ if (*f == '*') { do_assign = 0; ++f; } else do_assign = 1; /* Find the maximum field width. */ width = 0; while (isdigit(*f)) { width *= 10; width += *f++ - '0'; } if (width == 0) width = -1; /* Check for type modifiers. */ is_short = is_long = is_long_double = 0; while (*f == 'h' || *f == 'l' || *f == 'L') switch (*f++) { case 'h':#if 0 /* int's are short int's. */ is_short = 1; break;#endif case 'l':#if 0 if (is_long) /* A double `l' is equivalent to an `L'. */ is_longlong = 1; else /* int's are long int's. */ is_long = 1; break;#endif case 'L':#if 0 /* double's are long double's, and int's are long long int's. */ is_long_double = 1;#endif break; } /* End of the format string? */ if (*f == '\0') conv_error(); /* Find the conversion specifier. */ w = work; fc = *f++; if (fc != '[' && fc != 'c' && fc != 'n') /* Eat whitespace. */ while (isspace(c)) (void) inchar(); switch (fc) { case '%': /* Must match a literal '%'. */ if (c != fc) conv_error(); break; case 'n': /* Answer number of assignments done. */ if (do_assign) { if(++param_num>=argc) return -1; if(param_types[param_num] == FPL_INTVARARG) { ident = (struct Identifier *) param_array[param_num]; ident->data.variable.var.val32[0] = read_in; } else conv_error(); } break; case 'c': /* Match characters. */ if (do_assign) { if(++param_num>=argc) return -1; if(param_types[param_num] == FPL_STRVARARG) { ident = (struct Identifier *) param_array[param_num]; if(ident->data.variable.var.str[0]) FREE_KIND(ident->data.variable.var.str[0]); ident->data.variable.var.str[0]=NULL; } else conv_error(); } if (c == EOF) input_error(); if (width == -1) width = 1; if (do_assign) { SCALL(AddCharBuffer(scr, &ident->data.variable.var.str[0], ADD_RESET)); do { SCALL(AddCharBuffer(scr, &ident->data.variable.var.str[0], c)); } while (inchar() != EOF && --width > 0); } else while (inchar() != EOF && width > 0) --width; if (do_assign) { SCALL(AddCharBuffer(scr, &ident->data.variable.var.str[0], ADD_FLUSH)); ++done; } if (c == EOF) input_error(); break; case 's': /* Read a string. */ if (do_assign) { if(++param_num>=argc) return -1; if(param_types[param_num] == FPL_STRVARARG) { ident = (struct Identifier *) param_array[param_num]; if(ident->data.variable.var.str[0]) FREE_KIND(ident->data.variable.var.str[0]); ident->data.variable.var.str[0]=NULL; } else conv_error(); } if (c == EOF) input_error(); if(do_assign) { SCALL(AddCharBuffer(scr, &ident->data.variable.var.str[0], ADD_RESET)); } do { if (isspace(c)) break; if (do_assign) { SCALL(AddCharBuffer(scr, &ident->data.variable.var.str[0], c)); } } while (inchar() != EOF && (width <= 0 || --width > 0)); if (do_assign) { SCALL(AddCharBuffer(scr, &ident->data.variable.var.str[0], ADD_FLUSH)); ++done; } break; case 'x': /* Hexadecimal integer. */ case 'X': /* Ditto. */ base = 16; goto number; case 'o': /* Octal integer. */ base = 8; goto number; case 'u': /* Decimal integer. */ case 'd': /* Ditto. */ base = 10; goto number; case 'i': /* Generic number. */ base = 0; number:; if (c == EOF) input_error(); /* Check for a sign. */ if (c == '-' || c == '+') { *w++ = c; if (width > 0) --width; (void) inchar(); } /* Look for a leading indication of base. */ if (c == '0') { if (width > 0) --width; *w++ = '0'; (void) inchar(); if (tolower(c) == 'x') { if (base == 0) base = 16; if (base == 16) { if (width > 0) --width; (void) inchar(); } } else if (base == 0) base = 8; } if (base == 0) base = 10; /* Read the number into WORK. */ do { if (base == 16 ? !isxdigit(c) : (!isdigit(c) || c - '0' >= base)) break; *w++ = c; if (width > 0) --width; } while (inchar() != EOF && width != 0); if (w == work || (w - work == 1 && (work[0] == '+' || work[0] == '-'))) /* There was on number. */ conv_error(); /* Convert the number. */ *w = '\0'; num = Strtol(work, base, &w); if (w == work) conv_error(); if (do_assign) { if(++param_num>=argc) return -1; if(param_types[param_num] == FPL_INTVARARG) { ident = (struct Identifier *) param_array[param_num]; ident->data.variable.var.val32[0] = num; } else conv_error(); ++done; } break; case '[': /* Character class. */ if (do_assign) { if(++param_num>=argc) return -1; if(param_types[param_num] == FPL_STRVARARG) { ident = (struct Identifier *) param_array[param_num]; if(ident->data.variable.var.str[0]) FREE_KIND(ident->data.variable.var.str[0]); ident->data.variable.var.str[0]=NULL; } else conv_error(); } if (c == EOF) input_error(); if (*f == '^') { ++f; not_in = 1; } else not_in = 0; while ((fc = *f++) != '\0' && fc != ']') { if (fc == '-' && *f != '\0' && *f != ']' && w > work && w[-1] <= *f) /* Add all characters from the one before the '-' up to (but not including) the next format char. */ for (fc = w[-1] + 1; fc < *f; ++fc) *w++ = fc; else /* Add the character to the list. */ *w++ = fc; } if (fc == '\0') conv_error(); *w = '\0'; unum = read_in; if(do_assign) { SCALL(AddCharBuffer(scr, &ident->data.variable.var.str[0], ADD_RESET)); } do { if ((strchr(work, c) == NULL) != not_in) break; if (do_assign) { SCALL(AddCharBuffer(scr, &ident->data.variable.var.str[0], c)); } if (width > 0) --width; } while (inchar() != EOF && width != 0); if (read_in == unum) conv_error(); if (do_assign) { SCALL(AddCharBuffer(scr, &ident->data.variable.var.str[0], ADD_FLUSH)); ++done; } break; case 'p': /* Generic pointer. */ base = 16; /* A PTR must be the same size as a `long int'. */ is_long = 1; goto number; } } conv_error();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -