static str_t *extract_partial(struct msg_ac *msg) { char *cursor; char *c = msg->buffer.addr; char *end = msg->buffer.addr + msg->buffer.sz; for (int line = 1; line < msg->line; line++) { while (1) { if (c == end) return 0; if (*c == '\n') { c++; break; } c++; } } cursor = c + (msg->col - 1); c += msg->col - 2; while (isident(*c)) c--; c++; if (c == cursor) return 0; return str_from_cstr_len(c, cursor - c); }
void php_function(const char *&txt, PopupList &pul, BString &className, bool sorted) { BString label, function, params; txt = skip_whitespace(txt+8); const char *beg = txt; while (isident(*++txt)) ; function.SetTo(beg, txt-beg); txt = skip_whitespace(txt); if (*txt == '(') { const char* ptr = txt; txt = skip_block(txt+1, '(', ')'); params.SetTo(ptr+1, txt-ptr-2); params.Prepend(" ("); params.Append(")"); } if (sorted) { label << SORT_PREFIX_PHP; if (className != "") { label << className << "::"; } } else { if (className != "") { label << "• "; } } label << function << params; pul.insert(pul.end(), PopupMenu(label, function, beg)); } /* php_function */
static int cpp_keyword( LINE *lp, int off) { char temp[NSTRING]; register char *d = temp; register int n; static const struct { char *name; int code; } keyword_table[] = { { "if", CPP_IF }, { "ifdef", CPP_IF }, { "ifndef", CPP_IF }, { "elif", CPP_ELIF }, { "else", CPP_ELSE }, { "endif", CPP_ENDIF } }; while (off < llength(lp)) { n = lgetc(lp,off++); if ((d - temp < sizeof(temp)-2) && isident(n)) *d++ = (char)n; else break; } *d = EOS; for (n = 0; n < TABLESIZE(keyword_table); n++) if (!strcmp(temp, keyword_table[n].name)) return keyword_table[n].code; return CPP_UNKNOWN; }
bool IsValidIdentifier(const char *Str) { if (!isidentf(Str[0])) return false; while (char c = *Str++) if (!isident(c)) return false; return true; }
TBOOLEAN legal_identifier(char *p) { if (!p || !(*p) || isdigit((unsigned char)*p)) return FALSE; while (*p) { if (!isident(*p)) return FALSE; p++; } return TRUE; }
void get_terminal_name(unsigned char name[MAX_TERM_LEN]) { unsigned char *term = getenv("TERM"); int i; memset(name, 0, MAX_TERM_LEN); if (!term) return; for (i = 0; term[i] != 0 && i < MAX_TERM_LEN - 1; i++) name[i] = isident(term[i]) ? term[i] : '-'; }
static int bin_strftime(char *nam, char **argv, Options ops, UNUSED(int func)) { int bufsize, x; char *endptr = NULL, *scalar = NULL, *buffer; time_t secs; struct tm *t; if (OPT_ISSET(ops,'s')) { scalar = OPT_ARG(ops, 's'); if (!isident(scalar)) { zwarnnam(nam, "not an identifier: %s", scalar); return 1; } } if (OPT_ISSET(ops, 'r')) return reverse_strftime(nam, argv, scalar, OPT_ISSET(ops, 'q')); errno = 0; secs = (time_t)strtoul(argv[1], &endptr, 10); if (errno != 0) { zwarnnam(nam, "%s: %e", argv[1], errno); return 1; } else if (*endptr != '\0') { zwarnnam(nam, "%s: invalid decimal number", argv[1]); return 1; } t = localtime(&secs); if (!t) { zwarnnam(nam, "%s: unable to convert to time", argv[1]); return 1; } bufsize = strlen(argv[0]) * 8; buffer = zalloc(bufsize); for (x=0; x < 4; x++) { if (ztrftime(buffer, bufsize, argv[0], t) >= 0) break; buffer = zrealloc(buffer, bufsize *= 2); } if (scalar) { setsparam(scalar, metafy(buffer, -1, META_DUP)); } else { printf("%s\n", buffer); } zfree(buffer, bufsize); return 0; }
static int bin_syserror(char *nam, char **args, Options ops, UNUSED(int func)) { int num = 0; char *errvar = NULL, *msg, *pfx = "", *str; /* variable in which to write error message */ if (OPT_ISSET(ops, 'e')) { errvar = OPT_ARG(ops, 'e'); if (!isident(errvar)) { zwarnnam(nam, "not an identifier: %s", errvar); return 1; } } /* prefix for error message */ if (OPT_ISSET(ops, 'p')) pfx = OPT_ARG(ops, 'p'); if (!*args) num = errno; else { char *ptr = *args; while (*ptr && idigit(*ptr)) ptr++; if (!*ptr && ptr > *args) num = atoi(*args); else { const char **eptr; for (eptr = sys_errnames; *eptr; eptr++) { if (!strcmp(*eptr, *args)) { num = (eptr - sys_errnames) + 1; break; } } if (!*eptr) return 2; } } msg = strerror(num); if (errvar) { str = (char *)zalloc(strlen(msg) + strlen(pfx) + 1); sprintf(str, "%s%s", pfx, msg); setsparam(errvar, str); } else { fprintf(stderr, "%s%s\n", pfx, msg); } return 0; }
int rl_vi_eword (int count, int ignore) { while (count-- && rl_point < rl_end - 1) { if (!whitespace (rl_line_buffer[rl_point])) rl_point++; while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) rl_point++; if (rl_point < rl_end) { if (isident (rl_line_buffer[rl_point])) while (++rl_point < rl_end && isident (rl_line_buffer[rl_point])); else while (++rl_point < rl_end && !isident (rl_line_buffer[rl_point]) && !whitespace (rl_line_buffer[rl_point])); } rl_point--; } return (0); }
/* Read a C identifier beginning with "firstChar" and places it into "name". */ static void parseIdentifier (vString *const string, const int firstChar) { int c = firstChar; do { vStringPut (string, c); c = getcFromInputFile (); } while (isident (c)); vStringTerminate (string); if (!isspace (c)) ungetcToInputFile (c); /* unget non-identifier character */ }
int rl_vi_fword (int count, int ignore) { while (count-- && rl_point < (rl_end - 1)) { /* Move to white space (really non-identifer). */ if (isident (rl_line_buffer[rl_point])) { while (isident (rl_line_buffer[rl_point]) && rl_point < rl_end) rl_point++; } else /* if (!whitespace (rl_line_buffer[rl_point])) */ { while (!isident (rl_line_buffer[rl_point]) && !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) rl_point++; } /* Move past whitespace. */ while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) rl_point++; } return (0); }
static int get_token(char *token, int n) { int c = fileGetc(); int i = n; while (c != EOF && isident(c) && i < 1000) { token[i] = c; i++; c = fileGetc(); } if (c == EOF) return 0; if (i != n) { token[i] = '\0'; fileUngetc(c); return 1; } else { return 0; } }
static int bin_syswrite(char *nam, char **args, Options ops, UNUSED(int func)) { int outfd = 1, len, count, totcount; char *countvar = NULL; /* -o: output file descriptor if not stdout */ if (OPT_ISSET(ops, 'o')) { outfd = getposint(OPT_ARG(ops, 'o'), nam); if (outfd < 0) return 1; } /* -c: variable in which to store count of bytes written */ if (OPT_ISSET(ops, 'c')) { countvar = OPT_ARG(ops, 'c'); if (!isident(countvar)) { zwarnnam(nam, "not an identifier: %s", countvar); return 1; } } totcount = 0; unmetafy(*args, &len); while (len) { while ((count = write(outfd, *args, len)) < 0) { if (errno != EINTR || errflag || retflag || breaks || contflag) { if (countvar) setiparam(countvar, totcount); return 2; } } *args += count; totcount += count; len -= count; } if (countvar) setiparam(countvar, totcount); return 0; }
void php_class(const char *&txt, PopupList &pul, BString &className, bool sorted) { BString label; txt = skip_whitespace(txt+5); const char *beg = txt; while (isident(*++txt)) ; className.SetTo(beg, txt-beg); while (*++txt && *txt != '{') ; // txt = skip_whitespace(txt); // if (*txt == '(') { // const char* beg = txt; // txt = skip_block(txt+1, '(', ')'); // params.SetTo(beg+1, txt-beg-2); // params.Prepend(" ("); // params.Append(")"); // } if (!sorted) pul.insert(pul.end(), PopupMenu(className, className, beg, true)); } /* php_class */
int rl_vi_bword (int count, int ignore) { while (count-- && rl_point > 0) { int last_is_ident; /* If we are at the start of a word, move back to whitespace so we will go back to the start of the previous word. */ if (!whitespace (rl_line_buffer[rl_point]) && whitespace (rl_line_buffer[rl_point - 1])) rl_point--; /* If this character and the previous character are `opposite', move back so we don't get messed up by the rl_point++ down there in the while loop. Without this code, words like `l;' screw up the function. */ last_is_ident = isident (rl_line_buffer[rl_point - 1]); if ((isident (rl_line_buffer[rl_point]) && !last_is_ident) || (!isident (rl_line_buffer[rl_point]) && last_is_ident)) rl_point--; while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) rl_point--; if (rl_point > 0) { if (isident (rl_line_buffer[rl_point])) while (--rl_point >= 0 && isident (rl_line_buffer[rl_point])); else while (--rl_point >= 0 && !isident (rl_line_buffer[rl_point]) && !whitespace (rl_line_buffer[rl_point])); rl_point++; } } return (0); }
void FindClass(TagFileInfo* fi,const char* str,PTagArray ta) { FILE *g=fopen(fi->indexFile,"rb"); if(!g)return; int sz; fread(&sz,4,1,g); fseek(g,4+sz*4*2,SEEK_SET); fread(&sz,4,1,g); Vector<int> offsets; offsets.Init(sz); if(sz)fread(&offsets[0],4,sz,g); fclose(g); FILE *f=fopen(fi->filename,"rb"); if(!f)return; int len=strlen(str); int left=0; int right=offsets.Count()-1; int cmp; int pos; const char *cls; String base=fi->filename; int ri=base.RIndex("\\"); if(ri!=-1) { base.Delete(ri+1); } while(left<=right) { pos=(right+left)/2; fseek(f,offsets[pos],SEEK_SET); fgets(strbuf,sizeof(strbuf),f); cls=strstr(strbuf,"\tclass:"); if(!cls) { cls=strstr(strbuf,"\tstruct:"); if(!cls) { cls=""; }else { cls+=8; } }else { cls+=7; } cmp=strncmp(str,cls,len); if(!cmp && !isident(cls[len])) { break; }else if(cmp<=0) { right=pos-1; }else { left=pos+1; } } if(!cmp && !isident(cls[len])) { int endpos=pos; while(pos>0) { fseek(f,offsets[pos-1],SEEK_SET); fgets(strbuf,sizeof(strbuf),f); cls=strstr(strbuf,"\tclass:"); if(!cls) { cls=strstr(strbuf,"\tstruct:"); if(!cls) { cls=""; }else { cls+=8; } }else { cls+=7; } if(!strncmp(str,cls,len) && !isident(cls[len])) { pos--; }else { break; } } while(endpos<offsets.Count()-1) { fseek(f,offsets[endpos+1],SEEK_SET); fgets(strbuf,sizeof(strbuf),f); cls=strstr(strbuf,"\tclass:"); cls=strstr(strbuf,"\tclass:"); if(!cls) { cls=strstr(strbuf,"\tstruct:"); if(!cls) { cls=""; }else { cls+=8; } }else { cls+=7; } if(!strncmp(str,cls,len) && !isident(cls[len])) { endpos++; }else { break; } } Vector<char*> lines; for(int i=pos;i<=endpos;i++) { fseek(f,offsets[i],SEEK_SET); fgets(strbuf,sizeof(strbuf),f); lines.Push(strdup(strbuf)); } qsort(&lines[0],lines.Count(),4,StrCmp); for(int i=0;i<lines.Count();i++) { TagInfo *ti=ParseLine(lines[i],base); if(ti)ta->Push(ti); free(lines[i]); } } fclose(f); }
static void findHaskellTags (int is_literate) { vString *name = vStringNew (); char token[1001], arg[1001]; int c; int in_tex_lit_code = 0; c = get_next_char(); while (c != EOF) { if (c == '\n') { c = get_next_char(); continue; } if (isspace(c)) { skip_rest_of_line(); c = get_next_char(); continue; } if (is_literate && !in_tex_lit_code) { if (c == '>') { c = fileGetc(); if (c == ' ') { c = get_next_char(); if (!isident(c)) { skip_rest_of_line(); c = get_next_char(); continue; } } else { skip_rest_of_line(); c = get_next_char(); continue; } } else if (c == '\\') { int n = get_line(token); if (strncmp(token, "begin{code}", 11) == 0) { in_tex_lit_code = 1; c = get_next_char(); continue; } else { if (n > 0 && token[n-1] != '\n') skip_rest_of_line(); else c = get_next_char(); } continue; } else { skip_rest_of_line(); c = get_next_char(); continue; } } if (is_literate && in_tex_lit_code && c == '\\') { if (strncmp(token, "end{code}", 9) == 0) { in_tex_lit_code = 0; c = get_next_char(); continue; } } token[0] = c; token[1] = '\0'; if (!isident(c)) { skip_rest_of_line(); c = get_next_char(); continue; } if (!get_token(token, 1)) { c = get_next_char(); continue; } do { if ((c = fileGetc()) == EOF) return; } while (c == ' ' || c == '\t'); arg[0] = c; get_token(arg, 1); if (strcmp(token, "data") == 0 || strcmp(token, "newtype") == 0) { add_tag(arg, K_TYPE, name); c = inside_datatype(name); continue; } if (strcmp(token, "type") == 0) add_tag(arg, K_TYPE, name); else if (strcmp(token, "module") == 0) add_tag(arg, K_MODULE, name); else if (strcmp(token, "instance") == 0 || strcmp(token, "foreign") == 0 || strcmp(token, "import") == 0) ; else { if (arg[0] != ':') add_tag(token, K_FUNCTION, name); } skip_rest_of_line(); c = get_next_char(); } vStringDelete(name); }
static int bin_sysread(char *nam, char **args, Options ops, UNUSED(int func)) { int infd = 0, outfd = -1, bufsize = SYSREAD_BUFSIZE, count; char *outvar = NULL, *countvar = NULL, *inbuf; /* -i: input file descriptor if not stdin */ if (OPT_ISSET(ops, 'i')) { infd = getposint(OPT_ARG(ops, 'i'), nam); if (infd < 0) return 1; } /* -o: output file descriptor, else store in REPLY */ if (OPT_ISSET(ops, 'o')) { if (*args) { zwarnnam(nam, "no argument allowed with -o"); return 1; } outfd = getposint(OPT_ARG(ops, 'o'), nam); if (outfd < 0) return 1; } /* -s: buffer size if not default SYSREAD_BUFSIZE */ if (OPT_ISSET(ops, 's')) { bufsize = getposint(OPT_ARG(ops, 's'), nam); if (bufsize < 0) return 1; } /* -c: name of variable to store count of transferred bytes */ if (OPT_ISSET(ops, 'c')) { countvar = OPT_ARG(ops, 'c'); if (!isident(countvar)) { zwarnnam(nam, "not an identifier: %s", countvar); return 1; } } if (*args) { /* * Variable in which to store result if doing a plain read. * Default variable if not specified is REPLY. * If writing, only stuff we couldn't write is stored here, * no default in that case (we just discard it if no variable). */ outvar = *args; if (!isident(outvar)) { zwarnnam(nam, "not an identifier: %s", outvar); return 1; } } inbuf = zhalloc(bufsize); #if defined(HAVE_POLL) || defined(HAVE_SELECT) /* -t: timeout */ if (OPT_ISSET(ops, 't')) { # ifdef HAVE_POLL struct pollfd poll_fd; mnumber to_mn; int to_int, ret; poll_fd.fd = infd; poll_fd.events = POLLIN; to_mn = matheval(OPT_ARG(ops, 't')); if (errflag) return 1; if (to_mn.type == MN_FLOAT) to_int = (int) (1000 * to_mn.u.d); else to_int = 1000 * (int)to_mn.u.l; while ((ret = poll(&poll_fd, 1, to_int)) < 0) { if (errno != EINTR || errflag || retflag || breaks || contflag) break; } if (ret <= 0) { /* treat non-timeout error as error on read */ return ret ? 2 : 4; } # else /* using select */ struct timeval select_tv; fd_set fds; mnumber to_mn; int ret; FD_ZERO(&fds); FD_SET(infd, &fds); to_mn = matheval(OPT_ARG(ops, 't')); if (errflag) return 1; if (to_mn.type == MN_FLOAT) { select_tv.tv_sec = (int) to_mn.u.d; select_tv.tv_usec = (int) ((to_mn.u.d - select_tv.tv_sec) * 1e6); } else { select_tv.tv_sec = (int) to_mn.u.l; select_tv.tv_usec = 0; } while ((ret = select(infd+1, (SELECT_ARG_2_T) &fds, NULL, NULL,&select_tv)) < 1) { if (errno != EINTR || errflag || retflag || breaks || contflag) break; } if (ret <= 0) { /* treat non-timeout error as error on read */ return ret ? 2 : 4; } # endif } #endif while ((count = read(infd, inbuf, bufsize)) < 0) { if (errno != EINTR || errflag || retflag || breaks || contflag) break; } if (countvar) setiparam(countvar, count); if (count < 0) return 2; if (outfd >= 0) { if (!count) return 5; while (count > 0) { int ret; ret = write(outfd, inbuf, count); if (ret < 0) { if (errno == EINTR && !errflag && !retflag && !breaks && !contflag) continue; if (outvar) setsparam(outvar, metafy(inbuf, count, META_DUP)); if (countvar) setiparam(countvar, count); return 3; } inbuf += ret; count -= ret; } return 0; } if (!outvar) outvar = "REPLY"; /* do this even if we read zero bytes */ setsparam(outvar, metafy(inbuf, count, META_DUP)); return count ? 0 : 5; }
static void pibdump (struct _file_ const * file, char const * schema, unsigned extent, flag_t flags) { unsigned offset = 0; signed indent = 0; signed length = 0; unsigned lineno = 1; char symbol [0x0100]; char string [0x0400]; char * sp; signed c; output (indent++, "<%s xmlns:xsi='%s' xsi:noNamespaceSchemaLocation='%s'>", DATA_OBJECT, XML_NAMESPACE, schema); while ((c = getc (stdin)) != EOF) { if ((c == '#') || (c == ';')) { do { c = getc (stdin); } while (nobreak (c)); } if (isspace (c)) { if (c == '\n') { lineno++; } continue; } while (isdigit (c)) { length *= 10; length += c - '0'; c = getc (stdin); } while (isblank (c)) { c = getc (stdin); } sp = symbol; if (isalpha (c) || (c == '_')) { do { *sp++ = (char)(c); c = getc (stdin); } while (isident (c)); } *sp = (char)(0); while (isblank (c)) { c = getc (stdin); } if (c == '[') { #if 0 *sp++ = (char)(c); #endif c = getc (stdin); while (isblank (c)) { c = getc (stdin); } while (isdigit (c)) { #if 0 *sp++ = (char)(c); #endif c = getc (stdin); } while (isblank (c)) { c = getc (stdin); } if (c != ']') { error (1, EINVAL, "Have '%c' but need ']'", c); } #if 0 *sp++ = (char)(c); #endif c = getc (stdin); } *sp = (char)(0); while (isblank (c)) { c = getc (stdin); } sp = string; while (nobreak (c)) { *sp++ = (char)(c); c = getc (stdin); } *sp = (char)(0); if (length > 0) { #if defined (WIN32) byte * buffer = (byte *)(emalloc (length)); #else byte buffer [length]; #endif if (read (file->file, buffer, length) == length) { output (indent++, "<%s name='%s'>", DATA_MEMBER, symbol); #if 0 if (*string) { output (indent++, "<text>"); output (indent, "%s", string); output (indent--, "</text>"); } #endif output (indent++, "<%s>", DATA_OFFSET); output (indent, "%04X", offset); output (indent--, "</%s>", DATA_OFFSET); output (indent++, "<%s>", DATA_LENGTH); output (indent, "%d", length); output (indent--, "</%s>", DATA_LENGTH); output (indent++, "<%s>", DATA_MEMORY); for (c = 0; c < indent; c++) { printf ("\t"); } for (c = 0; c < length; c++) { printf ("%02X", buffer [c]); } printf ("\n"); output (indent--, "</%s>", DATA_MEMORY); output (indent--, "</%s>", DATA_MEMBER); } #if defined (WIN32) free (buffer); #endif } offset += length; length = 0; } output (indent--, "</%s>", DATA_OBJECT); if (_allclr (flags, PIB_SILENCE)) { if (offset != extent) { error (0, 0, "file %s is %d not %d bytes", file->name, extent, offset); } } return; }
const unsigned char* do_action( const unsigned char* action, CIStream* args, COStream out) { const unsigned char* as; unsigned char ac; int argn = 0; as = action; if ( as != NULL ) for ( ; ; ) { ac = *as++; switch (ac) { case PT_END: return as-1; case PT_SEPARATOR: return as; case PT_PUT_ARG: { CIStream arg = args[ (*as++) - 1 ]; cis_rewind(arg); cos_copy_input_stream(out,arg); break; } case PT_ONE_OPT: cos_putch(out,arg_char); break; case PT_DOMAIN: { CIStream inbuf; Pattern save_rule = current_rule; #if MAX_DOMAINS < 256 int domain = *as++ - 1; #else /* Get domain index as 14 bit little endian number */ int domain = ((unsigned char)*as++)&0x7f; domain = ((((unsigned char)*as++)&0x7f)<<7) | domain; #endif if ( as[0] == PT_VAR1 || ( as[0] == PT_OP && ( as[1] == OP_VAR || as[1] == OP_VAR_DFLT ) ) ) { /* for safety, copy the variable's value in case it is changed during translation. */ COStream outbuf; outbuf = make_buffer_output_stream(); as = do_action( as, args, outbuf ); inbuf = convert_output_to_input( outbuf ); } else /* optimized operand access */ inbuf = function_operand( &as, args ); #ifdef TRACE if ( trace_switch ) { int n; fprintf( stderr, "%12ld,%2d ", cis_line(input_stream), cis_column(input_stream)); for ( n = trace_indent ; n > 0 ; n-- ) fputc(' ',stderr); if ( cis_is_file(inbuf) ) { const char* inpath = cis_pathname(inbuf); if ( inpath == NULL ) inpath = "-"; fprintf( stderr, "@%s{@read{%s}}\n", domains[domain]->name, inpath); } else fprintf( stderr, "@%s{%.60s}\n", domains[domain]->name, cis_whole_string(inbuf)); ++trace_indent; } #endif if ( !translate( inbuf, domains[domain], out, NULL ) && cis_is_file(inbuf) && exit_status < EXS_FAIL ) exit_status = EXS_FAIL; #ifdef TRACE if ( trace_switch ) { --trace_indent; } #endif current_rule = save_rule; cis_close(inbuf); break; } case PT_VAR1: { char vname[2]; vname[0] = *as++; vname[1] = '\0'; put_var(out, vname, FALSE); break; } case PT_LINE: cos_freshline(out); break; case PT_MATCHED_TEXT: do_action( current_rule->pattern, args, out ); break; case PT_SPECIAL_ARG: #if MAX_DOMAINS >= 256 /* advance one more since 2 bytes for domain index */ case PT_RECUR: #endif as++; case PT_REGEXP: #if MAX_DOMAINS < 256 case PT_RECUR: #endif as++; case PT_MATCH_ANY: case PT_MATCH_ONE: { /* these will be encountered only when replaying the template as $0 */ CIStream arg = args[ argn++ ]; cis_rewind(arg); cos_copy_input_stream(out,arg); break; } case PT_AUX: as++; break; case PT_OP: { CIStream inbuf = NULL; enum Operators ac; ac = (enum Operators)*as++; switch(ac) { case OP_UNDEFINE: case OP_DEFINE: { inbuf = function_operand( &as, args ); read_patterns(inbuf, "", ac==OP_UNDEFINE); break; } case OP_SUBST: { int d; CIStream arg; Pattern save_rule = current_rule; arg = function_operand( &as, args ); d = read_patterns(arg," temp ",FALSE); inbuf = function_operand( &as, args ); translate ( inbuf, domains[d], out, NULL ); current_rule = save_rule; delete_domain(d); cis_close(arg); break; } case OP_VAR: { inbuf = function_operand( &as, args ); put_var(out, cis_whole_string(inbuf), FALSE ); break; } case OP_VAR_DFLT: { inbuf = function_operand( &as, args ); /* variable name */ if ( put_var(out, cis_whole_string(inbuf), TRUE ) ) as = skip_action(as); /* skip default value */ else as = do_action( as, args, out ); /* output default */ break; } case OP_SET: { CIStream name; name = function_operand( &as, args ); inbuf = function_operand( &as, args ); set_var( cis_whole_string(name), cis_whole_string(inbuf), cis_length(inbuf) ); cis_close(name); break; } case OP_BIND: { CIStream name; name = function_operand( &as, args ); inbuf = function_operand( &as, args ); bind_var( cis_whole_string(name), cis_whole_string(inbuf), cis_length(inbuf) ); cis_close(name); break; } case OP_UNBIND: { CIStream name; name = function_operand( &as, args ); unbind_var( cis_whole_string(name) ); cis_close(name); break; } case OP_APPEND: { CIStream name; name = function_operand( &as, args ); inbuf = function_operand( &as, args ); append_var( cis_whole_string(name), cis_whole_string(inbuf), cis_length(inbuf) ); cis_close(name); break; } case OP_INCR: case OP_DECR: { CIStream name; name = function_operand( &as, args ); incr_var( cis_whole_string(name), ac==OP_DECR? -1 : 1 ); cis_close(name); break; } case OP_GETENV: case OP_GETENV_DEFAULT: { CIStream dbuf = NULL; char* value; inbuf = function_operand( &as, args ); if ( ac == OP_GETENV_DEFAULT ) dbuf = function_operand( &as, args ); value = getenv(cis_whole_string(inbuf)); if ( value == NULL ) cos_copy_input_stream(out, dbuf); else cos_puts(out, value); cis_close(dbuf); break; } case OP_ERR: { static COStream err_stream = NULL; if ( err_stream == NULL ) err_stream = make_file_output_stream(stderr,"stderr"); as = do_action( as, args, err_stream ); break; } case OP_OUT: { as = do_action( as, args, output_stream ); break; } case OP_PATH: case OP_FILE: { const char* path = cis_pathname(input_stream); if ( path != NULL ) { if ( ac == OP_FILE ) path = pathname_name_and_type(path); cos_puts(out, path); } break; } case OP_OUTFILE: { const char* opath; opath = cos_pathname(out); if ( opath == NULL ) opath = cos_pathname(output_stream); cos_puts(out, opath); break; } case OP_LINE: { put_number(out, cis_line(input_stream)); break; } case OP_COL: { put_number(out, cis_column(input_stream)); break; } case OP_OUTCOL: { put_number(out, cos_column(output_stream)); break; } case OP_HELP: usage(); break; case OP_VERSION: cos_puts(out, Version); break; case OP_DATE: case OP_TIME: { time_t now; struct tm* ts; char tbuf [12]; now = time(NULL); ts = localtime(&now); if ( ac == OP_TIME ) sprintf(tbuf, "%02d:%02d:%02d", ts->tm_hour, ts->tm_min, ts->tm_sec); else sprintf(tbuf, "%02d/%02d/%d", ts->tm_mon + 1, ts->tm_mday, 1900 + ts->tm_year); cos_puts(out, tbuf); break; } case OP_DATIME: { time_t now; now = time(NULL); put_datime( out, &now ); break; } case OP_MODTIME: { time_t mtime; mtime = cis_mod_time(input_stream); if ( mtime != 0 ) put_datime( out, &mtime ); break; } case OP_PROBE: { inbuf = function_operand( &as, args ); cos_putch(out, probe_pathname(cis_whole_string(inbuf))); break; } case OP_READ: { const char* pathname; CIStream in; inbuf = function_operand( &as, args ); pathname = cis_whole_string(inbuf); close_output(pathname); in = open_input_file(pathname,binary); cos_copy_input_stream(out, in); cis_close(in); break; } case OP_WRITE: { COStream oldout; const char* pathname; oldout = output_stream; inbuf = function_operand( &as, args ); pathname = cis_whole_string(inbuf); output_stream = find_output_file(pathname,TRUE); as = do_action( as, args, output_stream ); output_stream = oldout; break; } case OP_CLOSE: { inbuf = function_operand( &as, args ); close_output(cis_whole_string(inbuf)); break; } case OP_COMBINEPATH: case OP_MERGEPATH: { CIStream dir; CIStream name; CIStream typ; dir = function_operand( &as, args ); name = function_operand( &as, args ); typ = function_operand( &as, args ); merge_pathnames( out, ac==OP_COMBINEPATH, cis_whole_string(dir), cis_whole_string(name), cis_whole_string(typ) ); cis_close(dir); cis_close(name); cis_close(typ); break; } case OP_RELPATH: { CIStream dir; dir = function_operand( &as, args ); inbuf = function_operand( &as, args ); cos_puts( out, relative_pathname(cis_whole_string(dir), cis_whole_string(inbuf)) ); cis_close(dir); break; } case OP_EXP_WILD: { inbuf = function_operand( &as, args ); expand_wildcard ( cis_whole_string(inbuf), out ); break; } case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_MOD: case OP_AND: case OP_OR: { long x,y,z; x = numeric_operand( &as, args ); y = numeric_operand( &as, args ); switch(ac) { case OP_ADD: z = x + y; break; case OP_SUB: z = x - y; break; case OP_MUL: z = x * y; break; case OP_DIV: z = x / y; break; case OP_MOD: z = x % y; break; case OP_AND: z = x & y; break; case OP_OR: z = x | y; break; default: /* can't happen; just to avoid compiler warning */ assert(FALSE); z = 0; break; } put_number(out,z); break; } case OP_NOT: put_number(out, ~ numeric_operand( &as, args ) ); break; case OP_RADIX: { int from, to; unsigned long value; char* string; char* end; const char* fmt; char buf[24]; /* enough for 64 bits in octal */ from = (int)numeric_operand( &as, args ); to = (int)numeric_operand( &as, args ); inbuf = function_operand( &as, args ); string = cis_whole_string(inbuf); value = strtoul( string, &end, from ); if ( *end != '\0' ) input_error ( input_stream, EXS_NUM, "Invalid argument for radix %d conversion: \"%.99s\"\n", from, string); if ( to == 8 ) fmt = "%lo"; else if ( to == 16 ) fmt = "%lX"; else { if ( to != 10 ) input_error ( input_stream, EXS_NUM, "Unsupported radix: %d\n", to); while ( isspace(string[0]) ) string++; fmt = (string[0]=='-') ? "%ld" : "%lu"; } sprintf(buf, fmt, value); cos_puts(out, buf); break; } case OP_STR_CMP: case OP_STRI_CMP: { /* string comparison */ CIStream x = function_operand( &as, args ); CIStream y = function_operand( &as, args ); const char* xs = cis_whole_string(x); const char* ys = cis_whole_string(y); int cmp; cmp = ac == OP_STRI_CMP ? stricmp(xs, ys) : strcmp(xs, ys); cis_close(x); cis_close(y); as = do_cmp( cmp, as, args, out); break; } case OP_NUM_CMP: { /* numeric comparison */ long x = numeric_operand( &as, args ); long y = numeric_operand( &as, args ); int cmp; if ( x < y ) cmp = -1; else if ( x == y ) cmp = 0; else cmp = 1; as = do_cmp( cmp, as, args, out); break; } case OP_LENGTH: { inbuf = function_operand( &as, args ); put_number(out, cis_length(inbuf)); break; } case OP_TAB: { int col; col = (int)numeric_operand( &as, args ); cos_spaces(out, col - (int)cos_column(out)); break; } case OP_WRAP: { unsigned length; unsigned col; inbuf = function_operand( &as, args ); length = cis_length(inbuf); col = cos_column(out); if ( ( ((int)(col + length)) > wrap_column && col > wrap_indent_length ) || ( col <= 1 && length > 0 ) ) { cos_freshline(out); cos_puts(out, wrap_indent); skip_whitespace(inbuf); } cos_copy_input_stream(out, inbuf); break; } case OP_SET_WRAP: { wrap_column = (int)numeric_operand( &as, args ); inbuf = function_operand( &as, args ); if ( wrap_indent != NULL ) free(wrap_indent); wrap_indent_length = cis_length(inbuf); wrap_indent = str_dup_len( cis_whole_string(inbuf), wrap_indent_length ); break; } case OP_RIGHT: case OP_LEFT: case OP_CENTER: { /* justify value in fixed-length field */ int field_length, string_length, left_pad, right_pad; field_length = (int)numeric_operand( &as, args ); inbuf = function_operand( &as, args ); string_length = cis_length(inbuf); left_pad = field_length - string_length; right_pad = 0; if ( left_pad < 0 ) left_pad = 0; if ( ac == OP_LEFT ) { right_pad = left_pad; left_pad = 0; } else if ( ac == OP_CENTER ) { left_pad = left_pad / 2; right_pad = field_length - string_length - left_pad; } cos_spaces(out, left_pad); cos_copy_input_stream(out, inbuf); cos_spaces(out, right_pad); break; } case OP_FILL_RIGHT: case OP_FILL_LEFT: case OP_FILL_CENTER: { /* justify value in fixed-length field */ int field_length, string_length, left_pad, right_pad; CIStream background; int i; background = function_operand( &as, args ); field_length = cis_length(background); inbuf = function_operand( &as, args ); string_length = cis_length(inbuf); left_pad = field_length - string_length; right_pad = 0; if ( left_pad < 0 ) left_pad = 0; if ( ac == OP_FILL_LEFT ) { right_pad = left_pad; left_pad = 0; } else if ( ac == OP_FILL_CENTER ) { left_pad = left_pad / 2; right_pad = field_length - string_length - left_pad; } else assert( ac == OP_FILL_RIGHT ); for ( i = left_pad ; i > 0 ; i-- ) cos_putch(out, cis_getch(background)); cos_copy_input_stream(out, inbuf); if ( right_pad > 0 ) { for ( i = string_length ; i > 0 ; i-- ) (void)cis_getch(background); cos_copy_input_stream(out, background); } cis_close(background); break; } case OP_SUBSTRING: { int skip_length, result_length, string_length; skip_length = (int)numeric_operand( &as, args ); result_length = (int)numeric_operand( &as, args ); inbuf = function_operand( &as, args ); string_length = cis_length(inbuf); if ( skip_length <= string_length ) { if ( skip_length < 0 ) skip_length = 0; if ( (skip_length + result_length) > string_length ) result_length = string_length - skip_length; cos_put_len(out, cis_whole_string(inbuf) + skip_length, result_length); } break; } case OP_DOWNCASE: case OP_UPCASE: { int cc; inbuf = function_operand( &as, args ); while ( (cc = cis_getch(inbuf)) != EOF ) cos_putch(out, ac==OP_DOWNCASE ? tolower(cc) : toupper(cc) ); break; } case OP_CHARINT: inbuf = function_operand( &as, args ); put_number(out, cis_getch(inbuf)); break; case OP_INTCHAR: cos_putch(out, (char)numeric_operand( &as, args )); break; case OP_REVERSE: { int len; const char* start; const char* ip; inbuf = function_operand( &as, args ); len = cis_length(inbuf); start = cis_whole_string(inbuf); for ( ip = start+len-1 ; ip >= start ; ip-- ) cos_putch(out, *ip); break; } case OP_SHELL: { const char* command; inbuf = function_operand( &as, args ); command = cis_whole_string(inbuf); fflush(stdout); if ( system( command ) < 0 ) { input_error ( input_stream, EXS_SHELL, "Failed shell command \"%.20s...\":\n", command ); perror("system"); } break; } case OP_EXIT: translation_status = Translate_Exited; break; case OP_FAIL: translation_status = Translate_Failed; break; case OP_END_OR_FAIL: /* ideally this should be testing whether the input stream has been advanced, but that is not so easy. */ translation_status = ( cis_out_length(out) == 0 )? Translate_Failed : Translate_Exited; break; case OP_EXIT_STATUS: exit_status = (Exit_States)(int)numeric_operand( &as, args ); break; case OP_ABORT: exit((int)(exit_status > EXS_FAIL ? exit_status : EXS_FAIL )); break; case OP_GET_SWITCH: case OP_SET_SWITCH: { const char* name; int* valpt; inbuf = function_operand( &as, args ); name = cis_whole_string(inbuf); valpt = find_switch(name); if ( valpt == NULL ) { input_error(input_stream, EXS_UNDEF, "Undefined switch name \"%.99s\"\n", name ); if ( ac == OP_SET_SWITCH ) (void)numeric_operand( &as, args ); } else { if ( ac == OP_SET_SWITCH ) *valpt = (int)numeric_operand( &as, args ); else put_number( out, *valpt ); } break; } case OP_SET_PARM: { const char* name; CIStream val; inbuf = function_operand( &as, args ); name = cis_whole_string(inbuf); val = function_operand( &as, args ); if ( !set_parm( name, cis_whole_string(val) ) ) input_error(input_stream, EXS_UNDEF, "Undefined parameter name \"%.99s\"\n", name ); cis_close(val); break; } case OP_SYNTAX: { const char* type; const char* charset; CIStream val; inbuf = function_operand( &as, args ); val = function_operand( &as, args ); charset = cis_whole_string(val); for ( type = cis_whole_string(inbuf) ; *type != '\0' ; type++ ) { const char* chars; char c[2]; if ( type[1] == '\0' ) chars = charset; else { c[0] = *charset++; c[1] = '\0'; chars = c; } if ( !set_syntax(type[0], chars) ) input_error(input_stream, EXS_UNDEF, "Undefined syntax type \"%.99s\"\n", type ); } cis_close(val); break; } case OP_DEFAULT_SYNTAX: initialize_syntax(); break; #ifndef MSDOS case OP_LOCALE: { const char* lname; inbuf = function_operand( &as, args ); lname = cis_whole_string(inbuf); if ( setlocale(LC_ALL, lname) == NULL ) input_error(input_stream, EXS_UNDEF, "Undefined locale \"%.99s\"\n", lname ); break; } #endif case OP_REPEAT: { long n = numeric_operand( &as, args ); if ( n <= 0 ) as = skip_action(as); else { const unsigned char* start = as; for ( ; n > 0 ; n-- ) as = do_action( start, args, out ); } break; } case OP_QUOTE: { inbuf = function_operand( &as, args ); quoted_copy( inbuf, out ); break; } default: fprintf(stderr, "Undefined op in action: %d\n", (int)ac); break; } /* end switch on ops */ cis_close(inbuf); break; } /* end PT_OP */ case PT_WORD_DELIM: case PT_ID_DELIM: /* Ignore if in expansion of "$0" */ if ( current_rule == NULL || action != current_rule->pattern ) { /* output a space if needed as a delimiter */ int prevch = cos_prevch(out); if ( prevch != EOF ) if ( ac == PT_ID_DELIM ? isident(prevch) : isalnum(prevch) ) cos_putch(out,' '); } break; #if 0 /* not needed now */ case PT_ARG_DELIM: if ( cos_prevch(out) != Arg_Delim ) cos_putch(out,Arg_Delim); break; #endif case PT_SPACE: { /* output a space if the last character is not white space */ int prevch = cos_prevch(out); if ( !isspace(prevch) ) cos_putch(out,' '); break; } case PT_SKIP_WHITE_SPACE: break; case PT_QUOTE: /* use next character literally */ ac = *as++; /* and fall-through */ default: cos_putch(out, ac); } /* end switch ac */ } /* end for */ /* can't ever get here, but return to avoid Gnu compiler warning. */ return as; }
static int bin_zsystem_flock(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) { int cloexec = 1, unlock = 0, readlock = 0; time_t timeout = 0; char *fdvar = NULL; #ifdef HAVE_FCNTL_H struct flock lck; int flock_fd, flags; #endif while (*args && **args == '-') { int opt; char *optptr = *args + 1, *optarg; args++; if (!*optptr || !strcmp(optptr, "-")) break; while ((opt = *optptr)) { switch (opt) { case 'e': /* keep lock on "exec" */ cloexec = 0; break; case 'f': /* variable for fd */ if (optptr[1]) { fdvar = optptr + 1; optptr += strlen(fdvar) - 1; } else if (*args) { fdvar = *args++; } if (fdvar == NULL || !isident(fdvar)) { zwarnnam(nam, "flock: option %c requires a variable name", opt); return 1; } break; case 'r': /* read lock rather than read-write lock */ readlock = 1; break; case 't': /* timeout in seconds */ if (optptr[1]) { optarg = optptr + 1; optptr += strlen(optarg) - 1; } else if (!*args) { zwarnnam(nam, "flock: option %c requires a numeric timeout", opt); return 1; } else { optarg = *args++; } timeout = (time_t)mathevali(optarg); break; case 'u': /* unlock: argument is fd */ unlock = 1; break; default: zwarnnam(nam, "flock: unknown option: %c", *optptr); return 1; } optptr++; } } if (!args[0]) { zwarnnam(nam, "flock: not enough arguments"); return 1; } if (args[1]) { zwarnnam(nam, "flock: too many arguments"); return 1; } #ifdef HAVE_FCNTL_H if (unlock) { flock_fd = (int)mathevali(args[0]); if (zcloselockfd(flock_fd) < 0) { zwarnnam(nam, "flock: file descriptor %d not in use for locking", flock_fd); return 1; } return 0; } if (readlock) flags = O_RDONLY | O_NOCTTY; else flags = O_RDWR | O_NOCTTY; if ((flock_fd = open(unmeta(args[0]), flags)) < 0) { zwarnnam(nam, "failed to open %s for writing: %e", args[0], errno); return 1; } flock_fd = movefd(flock_fd); if (flock_fd == -1) return 1; #ifdef FD_CLOEXEC if (cloexec) { long fdflags = fcntl(flock_fd, F_GETFD, 0); if (fdflags != (long)-1) fcntl(flock_fd, F_SETFD, fdflags | FD_CLOEXEC); } #endif addlockfd(flock_fd, cloexec); lck.l_type = readlock ? F_RDLCK : F_WRLCK; lck.l_whence = SEEK_SET; lck.l_start = 0; lck.l_len = 0; /* lock the whole file */ if (timeout > 0) { time_t end = time(NULL) + (time_t)timeout; while (fcntl(flock_fd, F_SETLK, &lck) < 0) { if (errflag) return 1; if (errno != EINTR && errno != EACCES && errno != EAGAIN) { zwarnnam(nam, "failed to lock file %s: %e", args[0], errno); return 1; } if (time(NULL) >= end) return 2; sleep(1); } } else { while (fcntl(flock_fd, F_SETLKW, &lck) < 0) { if (errflag) return 1; if (errno == EINTR) continue; zwarnnam(nam, "failed to lock file %s: %e", args[0], errno); return 1; } } if (fdvar) setiparam(fdvar, flock_fd); return 0; #else /* HAVE_FCNTL_H */ zwarnnam(nam, "flock: not implemented on this system"); return 255; #endif /* HAVE_FCNTL_H */ }
static void function (file const * file, off_t extent, flag_t flags) { unsigned object = 0; unsigned lineno = 0; unsigned offset = 0; unsigned length = 0; char memory [_ADDRSIZE + 1]; char symbol [_NAMESIZE]; char string [_LINESIZE]; char * sp; signed c; while ((c = getc (stdin)) != EOF) { if ((c == '#') || (c == ';')) { do { c = getc (stdin); } while (nobreak (c)); lineno++; continue; } if (isspace (c)) { if (c == '\n') { lineno++; } continue; } length = 0; while (isdigit (c)) { length *= 10; length += c - '0'; c = getc (stdin); } while (isblank (c)) { c = getc (stdin); } sp = symbol; if (isalpha (c) || (c == '_')) { do { * sp++ = (char) (c); c = getc (stdin); } while (isident (c)); } while (isblank (c)) { c = getc (stdin); } if (c == '[') { * sp++ = (char) (c); c = getc (stdin); while (isblank (c)) { c = getc (stdin); } while (isdigit (c)) { * sp++ = (char) (c); c = getc (stdin); } while (isblank (c)) { c = getc (stdin); } * sp = (char) (0); if (c != ']') { error (1, EINVAL, "Have '%s' without ']' on line %d", symbol, lineno); } * sp++ = (char) (c); c = getc (stdin); } * sp = (char) (0); while (isblank (c)) { c = getc (stdin); } sp = string; while (nobreak (c)) { * sp++ = (char) (c); c = getc (stdin); } * sp = (char) (0); if (length) { byte buffer [length]; if (read (file->file, buffer, length) == (signed) (length)) { if (! object++) { for (c = 0; c < _ADDRSIZE + 65; c++) { putc ('-', stdout); } putc ('\n', stdout); } printf ("%s %u %s\n", hexoffset (memory, sizeof (memory), offset), length, symbol); hexview (buffer, offset, length, stdout); for (c = 0; c < _ADDRSIZE + 65; c++) { putc ('-', stdout); } putc ('\n', stdout); } } offset += length; lineno++; } if (_allclr (flags, ODD_SILENCE)) { if (offset != (unsigned) (extent)) { error (0, 0, "%s has %u bytes, not " OFF_T_SPEC " bytes.", file->name, offset, extent); } } return; }
/* * scanner() breaks expression[] into lexical units, storing them in token[]. * The total number of tokens found is returned as the function * value. Scanning will stop when '\0' is found in expression[], or * when token[] is full. extend_input_line() is called to extend * expression array if needed. * * Scanning is performed by following rules: * * Current char token should contain * ------------- ----------------------- * 1. alpha,_ all following alpha-numerics * 2. digit 0 or more following digits, 0 or 1 decimal point, * 0 or more digits, 0 or 1 'e' or 'E', * 0 or more digits. * 3. ^,+,-,/ only current char * %,~,(,) * [,],;,:, * ?,comma * $ * 4. &,|,=,* current char; also next if next is same * 5. !,<,> current char; also next if next is = * 6. ", ' all chars up until matching quote * 7. # this token cuts off scanning of the line (DFK). * 8. ` (command substitution: all characters through the * matching backtic are replaced by the output of * the contained command, then scanning is restarted.) * EAM Jan 2010: Bugfix. No rule covered an initial period. This caused * string concatenation to fail for variables whose first * character is 'E' or 'e'. Now we add a 9th rule: * 9. . A period may be a token by itself (string concatenation) * or the start of a decimal number continuing with a digit * * white space between tokens is ignored */ int scanner(char **expressionp, size_t *expressionlenp) { int current; /* index of current char in expression[] */ char *expression = *expressionp; int quote; char brace; curly_brace_count = 0; for (current = t_num = 0; expression[current] != NUL; current++) { if (t_num + 1 >= token_table_size) { /* leave space for dummy end token */ extend_token_table(); } if (isspace((unsigned char) expression[current])) continue; /* skip the whitespace */ token[t_num].start_index = current; token[t_num].length = 1; token[t_num].is_token = TRUE; /* to start with... */ if (expression[current] == '`') { substitute(expressionp, expressionlenp, current); expression = *expressionp; /* expression might have moved */ current--; continue; } /* allow _ to be the first character of an identifier */ /* allow 8bit characters in identifiers */ if (isalpha((unsigned char)expression[current]) || (expression[current] == '_') || ALLOWED_8BITVAR(expression[current])) { while (isident(expression[current + 1])) APPEND_TOKEN; } else if (isdigit((unsigned char) expression[current])) { token[t_num].is_token = FALSE; token[t_num].length = get_num(&expression[current]); current += (token[t_num].length - 1); } else if (expression[current] == '.') { /* Rule 9 */ if (isdigit((unsigned char)expression[current+1])) { token[t_num].is_token = FALSE; token[t_num].length = get_num(&expression[current]); current += (token[t_num].length - 1); } /* do nothing if the . is a token by itself */ } else if (expression[current] == LBRACE) { int partial; token[t_num].is_token = FALSE; token[t_num].l_val.type = CMPLX; partial = sscanf(&expression[++current], "%lf , %lf %c", &token[t_num].l_val.v.cmplx_val.real, &token[t_num].l_val.v.cmplx_val.imag, &brace); if (partial <= 0) { curly_brace_count++; token[t_num++].is_token = TRUE; current--; continue; } if (partial != 3 || brace != RBRACE) int_error(t_num, "invalid complex constant"); token[t_num].length += 2; while (expression[++current] != RBRACE) { token[t_num].length++; if (expression[current] == NUL) /* { for vi % */ int_error(t_num, "no matching '}'"); } } else if (expression[current] == '\'' || expression[current] == '\"') { token[t_num].length++; quote = expression[current]; while (expression[++current] != quote) { if (!expression[current]) { expression[current] = quote; expression[current + 1] = NUL; break; } else if (quote == '\"' && expression[current] == '\\' && expression[current + 1]) { current++; token[t_num].length += 2; } else if (quote == '\"' && expression[current] == '`') { substitute(expressionp, expressionlenp, current); expression = *expressionp; /* it might have moved */ current--; } else if (quote == '\'' && expression[current+1] == '\'' && expression[current+2] == '\'') { /* look ahead: two subsequent single quotes * -> take them in */ current += 2; token[t_num].length += 3; } else token[t_num].length++; } } else switch (expression[current]) { case '#': #ifdef OLD_STYLE_CALL_ARGS /* FIXME: This ugly exception handles the old-style syntatic */ /* entity $# (number of arguments in "call" statement), which */ /* otherwise would be treated as introducing a comment. */ if ((t_num == 0) || (gp_input_line[token[t_num-1].start_index] != '$')) #endif goto endline; /* ignore the rest of the line */ case '^': case '+': case '-': case '/': case '%': case '~': case '(': case ')': case '[': case ']': case ';': case ':': case '?': case ',': case '$': break; case '}': /* complex constants will not end up here */ curly_brace_count--; break; case '&': case '|': case '=': case '*': if (expression[current] == expression[current + 1]) APPEND_TOKEN; break; case '!': case '>': if (expression[current + 1] == '=') APPEND_TOKEN; if (expression[current + 1] == '>') APPEND_TOKEN; break; case '<': if (expression[current + 1] == '=') APPEND_TOKEN; if (expression[current + 1] == '<') APPEND_TOKEN; break; default: int_error(t_num, "invalid character %c",expression[current]); } ++t_num; /* next token if not white space */ } endline: /* comments jump here to ignore line */ /* Now kludge an extra token which points to '\0' at end of expression[]. This is useful so printerror() looks nice even if we've fallen off the line. */ token[t_num].start_index = current; token[t_num].length = 0; /* print 3+4 then print 3+ is accepted without * this, since string is ignored if it is not * a token */ token[t_num].is_token = TRUE; return (t_num); }
static std::string selectorFromMethodDeclaration(std::string decl) { // Trim whitespace decl = trim(decl); if (decl.size() == 0) return std::string(); // Determine if this method is class or instance bool isClassMethod = false; if (decl[0] == '+') isClassMethod = true; else if (decl[0] != '-') return std::string(); // Not a method decl // Find colon std::string sel; if (isClassMethod) sel.push_back('+'); else sel.push_back('-'); IgnoringStage ignoringStage = IgnoringStage_Start; bool isStart = true; long bracketCount = 0; long variableLength = 0; for (long i = 0, len = decl.size(); i < len; i++) { char c = decl[i]; char next_c = i + 1 < len ? decl[i + 1] : '\0'; if (c == '/' && next_c == '/') { // Oops it's a comment for (; i < len; i++) { char c1 = decl[i]; char next_c1 = i + 1 < len ? decl[i + 1] : '\0'; if (c1 == '\n' || (c1 == '\r' && next_c1 != '\n')) break; } continue; } if (c == '/' && next_c == '*') { i += 2; // Don't allow /*/ // Oops it's a comment for (; i < len; i++) { char c1 = decl[i]; char next_c1 = i + 1 < len ? decl[i + 1] : '\0'; if (c1 == '*' && next_c1 == '/') break; } i++; continue; } if (ignoringStage == IgnoringStage_Start) { // printf("@start\n"); if (isspace(c)) continue; if (c == '-' || c == '+') continue; if (c == '(') { bracketCount++; ignoringStage = IgnoringStage_Brackets; // printf("->brackets\n"); continue; } if (isident(c)) { ignoringStage = IgnoringStage_NotIgnoring; // printf("->selector\n"); isStart = false; i--; continue; } return std::string(); // Not a method } if (ignoringStage == IgnoringStage_NotIgnoring) { // printf("@selector\n"); variableLength = 0; if (isspace(c)) continue; if (isident(c)) { sel.push_back(c); continue; } if (c == ':') { sel.push_back(c); ignoringStage = IgnoringStage_Colon; // printf("->colon\n"); continue; } return std::string(); // Not a method } else if (ignoringStage == IgnoringStage_Colon) { // printf("@colon\n"); if (isspace(c)) continue; if (c == '(') { bracketCount++; ignoringStage = IgnoringStage_Brackets; // printf("->brackets\n"); continue; } if (isident(c)) { ignoringStage = IgnoringStage_Variable; // printf("->variable\n"); i--; // Redo this loop as a variable continue; } return std::string(); // Not a method } else if (ignoringStage == IgnoringStage_Brackets) { // printf("@brackets\n"); if (c == '(') { bracketCount++; continue; } if (c == ')') { bracketCount--; if (bracketCount == 0) { if (isStart) { ignoringStage = IgnoringStage_NotIgnoring; // printf("->selector\n"); isStart = false; } else { ignoringStage = IgnoringStage_Variable; // printf("->variable\n"); } } continue; } continue; } else if (ignoringStage == IgnoringStage_Variable) { // printf("@variable\n"); if (isident(c)) { variableLength++; continue; } else { if (variableLength == 0) return std::string(); // Not a method. Needs an argument } if (isspace(c)) { ignoringStage = IgnoringStage_NotIgnoring; // printf("->selector\n"); continue; } if (c == ':') { sel.push_back(c); ignoringStage = IgnoringStage_Colon; // printf("->colon\n"); continue; } return std::string(); // Not a method. Needs an argument } } return sel; }
/* - regmatch - main matching routine * * Conceptually the strategy is simple: check to see whether the current * node matches, call self recursively to see whether the rest matches, * and then act accordingly. In practice we make some effort to avoid * recursion, in particular by going through "ordinary" nodes (that don't * need to know whether the rest of the match failed) by a loop instead of * by recursion. */ static int /* 0 failure, 1 success */ regmatch(char *prog) { register char *scan; /* Current node. */ char *next; /* Next node. */ extern char *strchr(); scan = prog; #ifdef DEBUG if (scan != NULL && regnarrate) { fprintf(stderr, "%s(\n", regprop(scan)); } #endif while (scan != NULL) { #ifdef DEBUG if (regnarrate) { fprintf(stderr, "%s...\n", regprop(scan)); } #endif next = regnext(scan); switch (OP(scan)) { case BOL: if (reginput != regbol) { return(0); } break; case EOL: if (regpeek(0) != '\0' && regpeek(0) != '\n') { return(0); } break; case BEGWORD: /* Match if current char isident * and previous char BOL or !ident */ if ((regpeek(0) == 0 || !isident(regpeek(0))) || (reginput != regbol && isident(regpeek(-1)))) { return(0); } break; case ENDWORD: /* Match if previous char isident * and current char EOL or !ident */ if ((regpeek(0) != 0 && isident(regpeek(0))) || reginput == regbol || !isident(regpeek(-1))) { return(0); } break; case WHITESP: /* match single whitespace */ if (regpeek(0) != 0 && !isspace(regpeek(0))) { return(0); } reginput++; break; case NWHITESP: /* don't match eol, or space or tab */ if (regpeek(0) == 0 || isspace(regpeek(0))) { return(0); } reginput++; break; case ALNUM: /* includes _ */ if (regpeek(0) == 0 || !isident(regpeek(0))) { return(0); } reginput++; break; case NALNUM: if (regpeek(0) == 0 || isident(regpeek(0))) { return(0); } reginput++; break; case DIGIT: if (regpeek(0) == 0 || !isdigit(regpeek(0))) { return(0); } reginput++; break; case NDIGIT: if (regpeek(0) == 0 || isdigit(regpeek(0))) { return(0); } reginput++; break; case PRINT: if (regpeek(0) == 0 || !(isprint(regpeek(0)) || isspace(regpeek(0)))) { return(0); } reginput++; break; case NPRINT: if (regpeek(0) == 0 || isprint(regpeek(0)) || isspace(regpeek(0))) { return(0); } reginput++; break; case ANY: if (regpeek(0) == '\0' || regpeek(0) == '\n') { return(0); } regseek(1); break; case EXACTLY: { register int len; register char *opnd; opnd = OPERAND(scan); /* Inline the first character, for speed. */ if (*opnd != regpeek(0)) { return(0); } len = strlen(opnd); if (len > 1 && strncmp(opnd, reginput, len) != 0) { return(0); } regseek(len); } break; case ANYOF: if (strchr(OPERAND(scan), regpeek(0)) == NULL) { return(0); } regseek(1); break; case ANYBUT: if (strchr(OPERAND(scan), regpeek(0)) != NULL) { return(0); } regseek(1); break; case NOTHING: break; case BACK: break; case OPEN+1: case OPEN+2: case OPEN+3: case OPEN+4: case OPEN+5: case OPEN+6: case OPEN+7: case OPEN+8: case OPEN+9: { register int no; register char *save; no = OP(scan) - OPEN; save = reginput; if (regmatch(next)) { /* * Don't set startp if some later * invocation of the same parentheses * already has. */ if (regstartp[no] == NULL) { regstartp[no] = save; } return(1); } else { return(0); } } break; case CLOSE+1: case CLOSE+2: case CLOSE+3: case CLOSE+4: case CLOSE+5: case CLOSE+6: case CLOSE+7: case CLOSE+8: case CLOSE+9: { register int no; register char *save; no = OP(scan) - CLOSE; save = reginput; if (regmatch(next)) { /* * Don't set endp if some later * invocation of the same parentheses * already has. */ if (regendp[no] == NULL) { regendp[no] = save; } return(1); } else { return(0); } } break; case BRANCH: { register char *save; if (OP(next) != BRANCH) { /* No choice. */ next = OPERAND(scan); /* Avoid recursion. */ } else { do { save = reginput; if (regmatch(OPERAND(scan))) { return(1); } reginput = save; scan = regnext(scan); } while (scan != NULL && OP(scan) == BRANCH); return(0); /* NOTREACHED */ } } break; case STAR: case PLUS: { register char nextch; register int no; register char *save; register int min; /* * Lookahead to avoid useless match attempts * when we know what character comes next. */ nextch = '\0'; if (OP(next) == EXACTLY) { nextch = *OPERAND(next); } min = (OP(scan) == STAR) ? 0 : 1; save = reginput; no = regrepeat(OPERAND(scan)); while (no >= min) { /* If it could work, try it. */ if (nextch == '\0' || regpeek(0) == nextch) { if (regmatch(next)) { return(1); } } /* Couldn't or didn't -- back up. */ no--; reginput = save + no; } return(0); } break; case MINMAX: { register char *save; unsigned char min; unsigned char max; register int no; next = OPERAND(scan); min = OP(next); next = OPERAND(next); max = OP(next); next = OPERAND(next); save = reginput; for (no = 0 ; no < min ; no++) { if (!regmatch(next)) { reginput = save; return(0); } } for ( ; no < max ; no++) { if (!regmatch(next)) { break; } } return(1); } break; case END: return(1); /* Success! */ break; default: SREerror("memory corruption"); return(0); break; } scan = next; } /* * We get here only if there's trouble -- normally "case END" is * the terminating point. */ SREerror("corrupted pointers"); return(0); }
/* - regrepeat - repeatedly match something simple, report how many */ static int regrepeat(char *p) { register int count = 0; register char *scan; register char *opnd; extern char *strchr(); scan = reginput; opnd = OPERAND(p); switch (OP(p)) { case ANY: /* make sure '.' doesn't match a \n character */ while (*scan != 0 && *scan != '\n') { count++; scan++; } break; case EXACTLY: while (*opnd == *scan) { count++; scan++; } break; case ANYOF: while (*scan != '\0' && strchr(opnd, *scan) != NULL) { count++; scan++; } break; case ANYBUT: while (*scan != '\0' && strchr(opnd, *scan) == NULL) { count++; scan++; } break; case WHITESP : while (*scan != 0 && isspace(*scan)) { count++; scan++; } break; case NWHITESP : while (*scan != 0 && !isspace(*scan)) { count++; scan++; } break; case DIGIT : while (*scan != 0 && isdigit(*scan)) { count++; scan++; } break; case NDIGIT : while (*scan != 0 && !isdigit(*scan)) { count++; scan++; } break; case ALNUM : while (*scan != 0 && isident(*scan)) { count++; scan++; } break; case NALNUM : while (*scan != 0 && !isident(*scan)) { count++; scan++; } break; case PRINT : while (*scan != 0 && (isprint(*scan) || isspace(*scan))) { count++; scan++; } break; case NPRINT : while (*scan != 0 && !(isprint(*scan) || isspace(*scan))) { count++; scan++; } break; default: /* Oh dear. Called inappropriately. */ SREerror("internal foulup"); count = 0; /* Best compromise. */ break; } reginput = scan; return(count); }
static int bin_zselect(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) { #ifdef HAVE_SELECT int i, fd, fdsetind = 0, fdmax = 0, fdcount; fd_set fdset[3]; const char fdchar[3] = "rwe"; struct timeval tv, *tvptr = NULL; char *outarray = "reply", **outdata, **outptr; char *outhash = NULL; LinkList fdlist; for (i = 0; i < 3; i++) FD_ZERO(fdset+i); for (; *args; args++) { char *argptr = *args, *endptr; zlong tempnum; if (*argptr == '-') { for (argptr++; *argptr; argptr++) { switch (*argptr) { /* * Array name for reply, if not $reply. * This gets set to e.g. `-r 0 -w 1' if 0 is ready * for reading and 1 is ready for writing. */ case 'a': case 'A': i = *argptr; if (argptr[1]) argptr++; else if (args[1]) { argptr = *++args; } else { zwarnnam(nam, "argument expected after -%c", *argptr); return 1; } if (idigit(*argptr) || !isident(argptr)) { zwarnnam(nam, "invalid array name: %s", argptr); return 1; } if (i == 'a') outarray = argptr; else outhash = argptr; /* set argptr to next to last char because of increment */ while (argptr[1]) argptr++; break; /* Following numbers indicate fd's for reading */ case 'r': fdsetind = 0; break; /* Following numbers indicate fd's for writing */ case 'w': fdsetind = 1; break; /* Following numbers indicate fd's for errors */ case 'e': fdsetind = 2; break; /* * Get a timeout value in hundredths of a second * (same units as KEYTIMEOUT). 0 means just poll. * If not given, blocks indefinitely. */ case 't': if (argptr[1]) argptr++; else if (args[1]) { argptr = *++args; } else { zwarnnam(nam, "argument expected after -%c", *argptr); return 1; } if (!idigit(*argptr)) { zwarnnam(nam, "number expected after -t"); return 1; } tempnum = zstrtol(argptr, &endptr, 10); if (*endptr) { zwarnnam(nam, "garbage after -t argument: %s", endptr); return 1; } /* timevalue now active */ tvptr = &tv; tv.tv_sec = (long)(tempnum / 100); tv.tv_usec = (long)(tempnum % 100) * 10000L; /* remember argptr is incremented at end of loop */ argptr = endptr - 1; break; /* Digits following option without arguments are fd's. */ default: if (handle_digits(nam, argptr, fdset+fdsetind, &fdmax)) return 1; } } } else if (handle_digits(nam, argptr, fdset+fdsetind, &fdmax)) return 1; } errno = 0; do { i = select(fdmax, (SELECT_ARG_2_T)fdset, (SELECT_ARG_2_T)(fdset+1), (SELECT_ARG_2_T)(fdset+2), tvptr); } while (i < 0 && errno == EINTR && !errflag); if (i <= 0) { if (i < 0) zwarnnam(nam, "error on select: %e", errno); /* else no fd's set. Presumably a timeout. */ return 1; } /* * Make a linked list of all file descriptors which are ready. * These go into an array preceded by -r, -w or -e for read, write, * error as appropriate. Typically there will only be one set * so this looks rather like overkill. */ fdlist = znewlinklist(); for (i = 0; i < 3; i++) { int doneit = 0; for (fd = 0; fd < fdmax; fd++) { if (FD_ISSET(fd, fdset+i)) { char buf[BDIGBUFSIZE]; if (outhash) { /* * Key/value pairs; keys are fd's (as strings), * value is a (possibly improper) subset of "rwe". */ LinkNode nptr; int found = 0; convbase(buf, fd, 10); for (nptr = firstnode(fdlist); nptr; nptr = nextnode(nextnode(nptr))) { if (!strcmp((char *)getdata(nptr), buf)) { /* Already there, add new character. */ void **dataptr = getaddrdata(nextnode(nptr)); char *data = (char *)*dataptr, *ptr; found = 1; if (!strchr(data, fdchar[i])) { strcpy(buf, data); for (ptr = buf; *ptr; ptr++) ; *ptr++ = fdchar[i]; *ptr = '\0'; zsfree(data); *dataptr = ztrdup(buf); } break; } } if (!found) { /* Add new key/value pair. */ zaddlinknode(fdlist, ztrdup(buf)); buf[0] = fdchar[i]; buf[1] = '\0'; zaddlinknode(fdlist, ztrdup(buf)); } } else { /* List of fd's preceded by -r, -w, -e. */ if (!doneit) { buf[0] = '-'; buf[1] = fdchar[i]; buf[2] = 0; zaddlinknode(fdlist, ztrdup(buf)); doneit = 1; } convbase(buf, fd, 10); zaddlinknode(fdlist, ztrdup(buf)); } } } } /* convert list to array */ fdcount = countlinknodes(fdlist); outptr = outdata = (char **)zalloc((fdcount+1)*sizeof(char *)); while (nonempty(fdlist)) *outptr++ = getlinknode(fdlist); *outptr = NULL; /* and store in array parameter */ if (outhash) sethparam(outhash, outdata); else setaparam(outarray, outdata); freelinklist(fdlist, NULL); return 0; #else /* TODO: use poll */ zerrnam(nam, "your system does not implement the select system call."); return 2; #endif }
int main() { int fd=open("test.js",O_RDONLY); char buf[1024]; int n=read(fd,buf,1024); int c,i,state='X',q,esc, last='X',pstate=0; for(;;) { for(i=0;i<n;i++) { c=buf[i]; putchar(c); switch(state) { case 'X': state_X: state='X'; if(c=='/') { state='/'; } else if(ispunctuation(c)) { parse(c); if(c==')') { last='E'; } else { last='P'; } } else if(isspace(c)) { state='W'; } else if(c=='\''||c=='"') { state='S'; q=c; esc=0; last='S'; } else if(isdigit(c)) { state='N'; last='N'; ident=b_ident; *ident++=c; } else if(isident(c)) { state='I'; last='I'; ident=b_ident; *ident++=c; } else { goto abort; } break; case 'W': if(isspace(c)) { /* nothing */ } else { goto state_X; } break; case 'I': if(isident(c)) { *ident++=c; } else { parse('I'); goto state_X; } break; case 'S': if(esc) { esc=0; } else if(c==q) { parse('S'); state='X'; } else if(c=='\\') { esc=1; } else { /* nothing */ } break; case 'N': if(isdigit(c) || c=='.') { *ident++=c; } else { parse('N'); goto state_X; } break; case '/': printf("\x1b[01;31m%c\x1b[00m" "\x1b[01;33m%.*s\x1b[00m",last,(int)(ident-b_ident),b_ident); if(c=='*') { state='C'; esc=0; } else if(c=='/') { state='c'; } else if(last!='N'&&last!='I'&&last!='E') { esc=0; state='R'; goto state_R; } else if(last=='I'&&strncmp(b_ident,"return",6)==0) { esc=0; state='R'; goto state_R; } else { parse('/'); goto state_X; } break; case 'R': state_R: if(esc) { esc=0; } else if(c=='\\') { esc=1; } else if(c=='/') { parse('R'); state='X'; } else { /* nothing */ } break; case 'C': if(esc) { if(c=='/') { state='X'; } else { esc=0; } } else if(c=='*') { esc=1; } else { /* nothing */ } break; case 'c': if(c=='\n'||c=='\r') { state='X'; } else { /* nothing */ } break; default: abort(); } if(pstate!=state) { printf("\x1b[01;32m%c\x1b[00m",state); } pstate=state; } n=read(fd,buf,1024); if(n==0) break; } return 0; abort: printf("\n Abort: char '%c' state '%c'\n",c,state); return 1; }
static enum parse_error parse_set_common(struct option *opt_tree, struct conf_parsing_state *state, struct string *mirror, int is_system_conf, int want_domain) { const unsigned char *domain_orig = NULL; size_t domain_len = 0; unsigned char *domain_copy = NULL; const unsigned char *optname_orig; size_t optname_len; unsigned char *optname_copy; skip_white(&state->pos); if (!*state->pos.look) return show_parse_error(state, ERROR_PARSE); if (want_domain) { domain_orig = state->pos.look; while (isident(*state->pos.look) || *state->pos.look == '*' || *state->pos.look == '.' || *state->pos.look == '+') state->pos.look++; domain_len = state->pos.look - domain_orig; skip_white(&state->pos); } /* Option name */ optname_orig = state->pos.look; while (is_option_name_char(*state->pos.look) || *state->pos.look == '.') state->pos.look++; optname_len = state->pos.look - optname_orig; skip_white(&state->pos); /* Equal sign */ if (*state->pos.look != '=') return show_parse_error(state, ERROR_PARSE); state->pos.look++; /* '=' */ skip_white(&state->pos); if (!*state->pos.look) return show_parse_error(state, ERROR_VALUE); optname_copy = memacpy(optname_orig, optname_len); if (!optname_copy) return show_parse_error(state, ERROR_NOMEM); if (want_domain) { domain_copy = memacpy(domain_orig, domain_len); if (!domain_copy) { mem_free(optname_copy); return show_parse_error(state, ERROR_NOMEM); } } /* Option value */ { struct option *opt; unsigned char *val; const struct conf_parsing_pos pos_before_value = state->pos; if (want_domain && *domain_copy) { struct option *domain_tree; domain_tree = get_domain_tree(domain_copy); if (!domain_tree) { mem_free(domain_copy); mem_free(optname_copy); skip_option_value(&state->pos); return show_parse_error(state, ERROR_NOMEM); } if (mirror) { opt = get_opt_rec_real(domain_tree, optname_copy); } else { opt = get_opt_rec(opt_tree, optname_copy); if (opt) { opt = get_option_shadow(opt, opt_tree, domain_tree); if (!opt) { mem_free(domain_copy); mem_free(optname_copy); skip_option_value(&state->pos); return show_parse_error(state, ERROR_NOMEM); } } } } else { opt = mirror ? get_opt_rec_real(opt_tree, optname_copy) : get_opt_rec(opt_tree, optname_copy); } if (want_domain) mem_free(domain_copy); domain_copy = NULL; mem_free(optname_copy); optname_copy = NULL; if (!opt || (opt->flags & OPT_HIDDEN)) { show_parse_error(state, ERROR_OPTION); skip_option_value(&state->pos); return ERROR_OPTION; /* TODO: Distinguish between two scenarios: * - A newer version of ELinks has saved an * option that this version does not recognize. * The option must be preserved. (This works.) * - The user has added an option, saved * elinks.conf, restarted ELinks, deleted the * option, and is now saving elinks.conf again. * The option should be rewritten to "unset". * (This does not work yet.) * In both cases, ELinks has no struct option * for that name. Possible fixes: * - If the tree has OPT_AUTOCREATE, then * assume the user had created that option, * and rewrite it to "unset". Otherwise, * keep it. * - When the user deletes an option, just mark * it with OPT_DELETED, and keep it in memory * as long as OPT_TOUCHED is set. */ } if (!option_types[opt->type].read) { show_parse_error(state, ERROR_VALUE); skip_option_value(&state->pos); return ERROR_VALUE; } val = option_types[opt->type].read(opt, &state->pos.look, &state->pos.line); if (!val) { /* The reader function failed. Jump back to * the beginning of the value and skip it with * the generic code. For the error message, * use the line number at the beginning of the * value, because the ending position is not * interesting if there is an unclosed quote. */ state->pos = pos_before_value; show_parse_error(state, ERROR_VALUE); skip_option_value(&state->pos); return ERROR_VALUE; } if (!mirror) { /* loading a configuration file */ if (!option_types[opt->type].set || !option_types[opt->type].set(opt, val)) { mem_free(val); return show_parse_error(state, ERROR_VALUE); } } else if (is_system_conf) { /* scanning a file that will not be rewritten */ struct option *flagsite = indirect_option(opt); if (!(flagsite->flags & OPT_DELETED) && option_types[opt->type].equals && option_types[opt->type].equals(opt, val)) flagsite->flags &= ~OPT_MUST_SAVE; else flagsite->flags |= OPT_MUST_SAVE; } else { /* rewriting a configuration file */ struct option *flagsite = indirect_option(opt); if (flagsite->flags & OPT_DELETED) { /* Replace the "set" command with an * "unset" command. */ add_to_string(mirror, "unset "); add_bytes_to_string(mirror, optname_orig, optname_len); state->mirrored = state->pos.look; } else if (option_types[opt->type].write) { add_bytes_to_string(mirror, state->mirrored, pos_before_value.look - state->mirrored); option_types[opt->type].write(opt, mirror); state->mirrored = state->pos.look; } /* Remember that the option need not be * written to the end of the file. */ flagsite->flags &= ~OPT_MUST_SAVE; } mem_free(val); } return ERROR_NONE; }
void vcc_Lexer(struct tokenlist *tl, struct source *sp) { const char *p, *q; unsigned u; tl->src = sp; for (p = sp->b; p < sp->e; ) { /* Skip any whitespace */ if (isspace(*p)) { p++; continue; } /* Skip '#.*\n' comments */ if (*p == '#') { while (p < sp->e && *p != '\n') p++; continue; } /* Skip C-style comments */ if (*p == '/' && p[1] == '*') { for (q = p + 2; q < sp->e; q++) { if (*q == '/' && q[1] == '*') { vsb_printf(tl->sb, "/* ... */ comment contains /*\n"); vcc_AddToken(tl, EOI, p, p + 2); vcc_ErrWhere(tl, tl->t); vcc_AddToken(tl, EOI, q, q + 2); vcc_ErrWhere(tl, tl->t); return; } if (*q == '*' && q[1] == '/') { p = q + 2; break; } } if (q < sp->e) continue; vcc_AddToken(tl, EOI, p, p + 2); vsb_printf(tl->sb, "Unterminated /* ... */ comment, starting at\n"); vcc_ErrWhere(tl, tl->t); return; } /* Skip C++-style comments */ if (*p == '/' && p[1] == '/') { while (p < sp->e && *p != '\n') p++; continue; } /* Recognize inline C-code */ if (*p == 'C' && p[1] == '{') { for (q = p + 2; q < sp->e; q++) { if (*q == '}' && q[1] == 'C') { vcc_AddToken(tl, CSRC, p, q + 2); break; } } if (q < sp->e) { p = q + 2; continue; } vcc_AddToken(tl, EOI, p, p + 2); vsb_printf(tl->sb, "Unterminated inline C source, starting at\n"); vcc_ErrWhere(tl, tl->t); return; } /* Recognize long-strings */ if (*p == '{' && p[1] == '"') { for (q = p + 2; q < sp->e; q++) { if (*q == '"' && q[1] == '}') { vcc_AddToken(tl, CSTR, p, q + 2); break; } } if (q < sp->e) { p = q + 2; u = tl->t->e - tl->t->b; u -= 4; /* {" ... "} */ tl->t->dec = TlAlloc(tl, u + 1 ); AN(tl->t->dec); memcpy(tl->t->dec, tl->t->b + 2, u); tl->t->dec[u] = '\0'; continue; } vcc_AddToken(tl, EOI, p, p + 2); vsb_printf(tl->sb, "Unterminated long-string, starting at\n"); vcc_ErrWhere(tl, tl->t); return; } /* Match for the fixed tokens (see token.tcl) */ u = vcl_fixed_token(p, &q); if (u != 0) { vcc_AddToken(tl, u, p, q); p = q; continue; } /* Match strings, with \\ and \" escapes */ if (*p == '"') { for (q = p + 1; q < sp->e; q++) { if (*q == '"') { q++; break; } if (*q == '\r' || *q == '\n') { vcc_AddToken(tl, EOI, p, q); vsb_printf(tl->sb, "Unterminated string at\n"); vcc_ErrWhere(tl, tl->t); return; } } vcc_AddToken(tl, CSTR, p, q); if (vcc_decstr(tl)) return; p = q; continue; } /* Match Identifiers */ if (isident1(*p)) { for (q = p; q < sp->e; q++) if (!isident(*q)) break; if (isvar(*q)) { for (; q < sp->e; q++) if (!isvar(*q)) break; vcc_AddToken(tl, VAR, p, q); } else { vcc_AddToken(tl, ID, p, q); } p = q; continue; } /* Match numbers { [0-9]+ } */ if (isdigit(*p)) { for (q = p; q < sp->e; q++) if (!isdigit(*q)) break; vcc_AddToken(tl, CNUM, p, q); p = q; continue; } vcc_AddToken(tl, EOI, p, p + 1); vsb_printf(tl->sb, "Syntax error at\n"); vcc_ErrWhere(tl, tl->t); return; } }