BOOL wait_for_call(COM_HANDLE com_handle) { char str[128]; char* p; BOOL result=TRUE; DWORD events=0; time_t start=time(NULL); ZERO_VAR(cid_name); ZERO_VAR(cid_number); if(!comRaiseDTR(com_handle)) lprintf(LOG_ERR,"ERROR %u raising DTR", COM_ERROR_VALUE); if(com_alreadyconnected) return TRUE; if(!mdm_null) { if(mdm_init[0]) { lprintf(LOG_INFO,"Initializing modem:"); if(!modem_command(com_handle, mdm_init)) return FALSE; } if(!mdm_manswer && mdm_autoans[0]) { lprintf(LOG_INFO,"Setting modem to auto-answer:"); if(!modem_command(com_handle, mdm_autoans)) return FALSE; } if(mdm_cid[0]) { lprintf(LOG_INFO,"Enabling modem Caller-ID:"); if(!modem_command(com_handle, mdm_cid)) return FALSE; } } lprintf(LOG_INFO,"Waiting for incoming call (%s) ...", mdm_manswer ? "Ring Indication" : "Carrier Detect"); while(1) { if(terminated) return FALSE; if(comReadLine(com_handle, str, sizeof(str), /* timeout (ms): */250) > 0) { truncsp(str); if(str[0]==0) continue; lprintf(LOG_DEBUG,"Received from modem: '%s'", str); p=str; SKIP_WHITESPACE(p); if(*p) { lprintf(LOG_INFO, "Modem Message: %s", p); if(strncmp(p,"CONNECT ",8)==0) { long rate=atoi(p+8); if(rate) SAFEPRINTF2(termspeed,"%u,%u", rate, rate); } else if(strncmp(p,"NMBR",4)==0 || strncmp(p,"MESG",4)==0) { p+=4; FIND_CHAR(p,'='); SKIP_CHAR(p,'='); SKIP_WHITESPACE(p); if(cid_number[0]==0) /* Don't overwrite, if multiple messages received */ SAFECOPY(cid_number, p); } else if(strncmp(p,"NAME",4)==0) { p+=4; FIND_CHAR(p,'='); SKIP_CHAR(p,'='); SKIP_WHITESPACE(p); SAFECOPY(cid_name, p); } else if(strcmp(p,"NO CARRIER")==0) { ZERO_VAR(cid_name); ZERO_VAR(cid_number); } else if(mdm_ring[0] && strcmp(p,mdm_ring)==0 && mdm_manswer && mdm_answer[0]) { if(!modem_send(com_handle, mdm_answer)) { lprintf(LOG_ERR,"ERROR %u sending modem command (%s) on %s" ,COM_ERROR_VALUE, mdm_answer, com_dev); } } } continue; /* don't check DCD until we've received all the modem msgs */ } if(carrier_detect(com_handle)) break; if(mdm_reinit && (time(NULL)-start)/60 >= mdm_reinit) { lprintf(LOG_INFO,"Re-initialization timer elapsed: %u minutes", mdm_reinit); return TRUE; } } if(strcmp(cid_name,"P")==0) SAFECOPY(cid_name,"Private"); else if(strcmp(cid_name,"O")==0) SAFECOPY(cid_name,"Out-of-area"); if(strcmp(cid_number,"P")==0) SAFECOPY(cid_number,"Private"); else if(strcmp(cid_number,"O")==0) SAFECOPY(cid_number,"Out-of-area"); lprintf(LOG_INFO,"Carrier detected"); return TRUE; }
int main(int argc, char **argv) { const char *b, *e, *p; const char *output_file = NULL; int f, tot, last, linenum, err, parse_err; struct timer *t = NULL, *t2; struct eb32_node *n; int val, test; int array[5]; int filter_acc_delay = 0, filter_acc_count = 0; int filter_time_resp = 0; int skip_fields = 1; argc--; argv++; while (argc > 0) { if (*argv[0] != '-') break; if (strcmp(argv[0], "-ad") == 0) { if (argc < 2) die("missing option for -ad"); argc--; argv++; filter |= FILT_ACC_DELAY; filter_acc_delay = atol(*argv); } else if (strcmp(argv[0], "-ac") == 0) { if (argc < 2) die("missing option for -ac"); argc--; argv++; filter |= FILT_ACC_COUNT; filter_acc_count = atol(*argv); } else if (strcmp(argv[0], "-rt") == 0) { if (argc < 2) die("missing option for -rt"); argc--; argv++; filter |= FILT_TIME_RESP; filter_time_resp = atol(*argv); } else if (strcmp(argv[0], "-RT") == 0) { if (argc < 2) die("missing option for -RT"); argc--; argv++; filter |= FILT_TIME_RESP | FILT_INVERT_TIME_RESP; filter_time_resp = atol(*argv); } else if (strcmp(argv[0], "-s") == 0) { if (argc < 2) die("missing option for -s"); argc--; argv++; skip_fields = atol(*argv); } else if (strcmp(argv[0], "-e") == 0) filter |= FILT_ERRORS_ONLY; else if (strcmp(argv[0], "-E") == 0) filter |= FILT_ERRORS_ONLY | FILT_INVERT_ERRORS; else if (strcmp(argv[0], "-c") == 0) filter |= FILT_COUNT_ONLY; else if (strcmp(argv[0], "-q") == 0) filter |= FILT_QUIET; else if (strcmp(argv[0], "-v") == 0) filter_invert = !filter_invert; else if (strcmp(argv[0], "-gt") == 0) filter |= FILT_GRAPH_TIMERS; else if (strcmp(argv[0], "-pct") == 0) filter |= FILT_PERCENTILE; else if (strcmp(argv[0], "-o") == 0) { if (output_file) die("Fatal: output file name already specified.\n"); if (argc < 2) die("Fatal: missing output file name.\n"); output_file = argv[1]; } argc--; argv++; } if (!filter) die("No action specified.\n"); if (filter & FILT_ACC_COUNT && !filter_acc_count) filter_acc_count=1; if (filter & FILT_ACC_DELAY && !filter_acc_delay) filter_acc_delay = 1; linenum = 0; tot = 0; parse_err = 0; while ((line = fgets2(stdin)) != NULL) { linenum++; test = 1; if (filter & FILT_TIME_RESP) { int tps; /* only report lines with response times larger than filter_time_resp */ b = field_start(line, TIME_FIELD + skip_fields); if (!*b) { truncated_line(linenum, line); continue; } e = field_stop(b + 1); /* we have field TIME_FIELD in [b]..[e-1] */ p = b; err = 0; for (f = 0; f < 4 && *p; f++) { tps = str2ic(p); if (tps < 0) { tps = -1; err = 1; } SKIP_CHAR(p, '/'); } if (f < 4) { parse_err++; continue; } test &= (tps >= filter_time_resp) ^ !!(filter & FILT_INVERT_TIME_RESP); } if (filter & FILT_ERRORS_ONLY) { /* only report erroneous status codes */ b = field_start(line, STATUS_FIELD + skip_fields); if (!*b) { truncated_line(linenum, line); continue; } if (*b == '-') { test &= !!(filter & FILT_INVERT_ERRORS); } else { val = strl2ui(b, 3); test &= (val >= 500 && val <= 599) ^ !!(filter & FILT_INVERT_ERRORS); } } if (filter & (FILT_ACC_COUNT|FILT_ACC_DELAY)) { b = field_start(line, ACCEPT_FIELD + skip_fields); if (!*b) { truncated_line(linenum, line); continue; } tot++; val = convert_date(b); //printf("date=%s => %d\n", b, val); if (val < 0) { parse_err++; continue; } t2 = insert_value(&timers[0], &t, val); t2->count++; continue; } if (filter & (FILT_GRAPH_TIMERS|FILT_PERCENTILE)) { int f; b = field_start(line, TIME_FIELD + skip_fields); if (!*b) { truncated_line(linenum, line); continue; } e = field_stop(b + 1); /* we have field TIME_FIELD in [b]..[e-1] */ p = b; err = 0; for (f = 0; f < 5 && *p; f++) { array[f] = str2ic(p); if (array[f] < 0) { array[f] = -1; err = 1; } SKIP_CHAR(p, '/'); } if (f < 5) { parse_err++; continue; } /* if we find at least one negative time, we count one error * with a time equal to the total session time. This will * emphasize quantum timing effects associated to known * timeouts. Note that on some buggy machines, it is possible * that the total time is negative, hence the reason to reset * it. */ if (filter & FILT_GRAPH_TIMERS) { if (err) { if (array[4] < 0) array[4] = -1; t2 = insert_timer(&timers[0], &t, array[4]); // total time t2->count++; } else { int v; t2 = insert_timer(&timers[1], &t, array[0]); t2->count++; // req t2 = insert_timer(&timers[2], &t, array[2]); t2->count++; // conn t2 = insert_timer(&timers[3], &t, array[3]); t2->count++; // resp v = array[4] - array[0] - array[1] - array[2] - array[3]; // data time if (v < 0 && !(filter & FILT_QUIET)) fprintf(stderr, "ERR: %s (%d %d %d %d %d => %d)\n", line, array[0], array[1], array[2], array[3], array[4], v); t2 = insert_timer(&timers[4], &t, v); t2->count++; tot++; } } else { /* percentile */ if (err) { if (array[4] < 0) array[4] = -1; t2 = insert_value(&timers[0], &t, array[4]); // total time t2->count++; } else { int v; t2 = insert_value(&timers[1], &t, array[0]); t2->count++; // req t2 = insert_value(&timers[2], &t, array[2]); t2->count++; // conn t2 = insert_value(&timers[3], &t, array[3]); t2->count++; // resp v = array[4] - array[0] - array[1] - array[2] - array[3]; // data time if (v < 0 && !(filter & FILT_QUIET)) fprintf(stderr, "ERR: %s (%d %d %d %d %d => %d)\n", line, array[0], array[1], array[2], array[3], array[4], v); t2 = insert_value(&timers[4], &t, v); t2->count++; tot++; } } continue; } test ^= filter_invert; if (!test) continue; /* all other cases mean we just want to count lines */ tot++; if (!(filter & FILT_COUNT_ONLY)) puts(line); } if (t) free(t); if (filter & FILT_COUNT_ONLY) { printf("%d\n", tot); exit(0); } if (filter & FILT_ERRORS_ONLY) exit(0); if (filter & (FILT_ACC_COUNT|FILT_ACC_DELAY)) { /* sort and count all timers. Output will look like this : * <accept_date> <delta_ms from previous one> <nb entries> */ n = eb32_first(&timers[0]); if (n) last = n->key; while (n) { unsigned int d, h, m, s, ms; t = container_of(n, struct timer, node); h = n->key; d = h - last; last = h; if (d >= filter_acc_delay && t->count >= filter_acc_count) { ms = h % 1000; h = h / 1000; s = h % 60; h = h / 60; m = h % 60; h = h / 60; tot++; printf("%02d:%02d:%02d.%03d %d %d %d\n", h, m, s, ms, last, d, t->count); } n = eb32_next(n); } }
/* Important change as of Nov-16-2006, 'cmdline' may contain args */ long sbbs_t::exec_bin(const char *cmdline, csi_t *csi, const char* startup_dir) { char str[MAX_PATH+1]; char mod[MAX_PATH+1]; char modname[MAX_PATH+1]; char* p; int file; csi_t bin; SAFECOPY(mod,cmdline); p=mod; FIND_CHAR(p,' '); if(*p) { *p=0; /* terminate 'mod' */ p++; /* skip space */ SKIP_CHAR(p,' '); /* skip more spaces */ } if(*p) strcpy(main_csi.str, p); #ifdef JAVASCRIPT if((p=getfext(mod))!=NULL && stricmp(p,".js")==0) return(js_execfile(cmdline, startup_dir)); if(p==NULL && startup_dir!=NULL && *startup_dir) { SAFEPRINTF2(str,"%s%s.js", startup_dir, mod); if(fexistcase(str)) return(js_execfile(cmdline, startup_dir)); } if(cfg.mods_dir[0]) { SAFEPRINTF2(str,"%s%s.js",cfg.mods_dir,mod); if(fexistcase(str)) return(js_execfile(cmdline, startup_dir)); } #endif SAFECOPY(modname,mod); if(!strchr(modname,'.')) strcat(modname,".bin"); SAFEPRINTF2(str,"%s%s",cfg.mods_dir,modname); if(cfg.mods_dir[0]==0 || !fexistcase(str)) { #ifdef JAVASCRIPT SAFEPRINTF2(str,"%s%s.js",cfg.exec_dir,mod); if(fexistcase(str)) return(js_execfile(cmdline, startup_dir)); #endif SAFEPRINTF2(str,"%s%s",cfg.exec_dir,modname); fexistcase(str); } if((file=nopen(str,O_RDONLY))==-1) { errormsg(WHERE,ERR_OPEN,str,O_RDONLY); return(-1); } memcpy(&bin,csi,sizeof(csi_t)); clearvars(&bin); bin.length=(uint32_t)filelength(file); if((bin.cs=(uchar *)malloc(bin.length))==NULL) { close(file); errormsg(WHERE,ERR_ALLOC,str,bin.length); return(-1); } if(lread(file,bin.cs,bin.length)!=bin.length) { close(file); errormsg(WHERE,ERR_READ,str,bin.length); free(bin.cs); return(-1); } close(file); bin.ip=bin.cs; bin.rets=0; bin.cmdrets=0; bin.misc=0; while(exec(&bin)==0) if(!(bin.misc&CS_OFFLINE_EXEC)) { checkline(); if(!online) break; } freevars(&bin); free(bin.cs); csi->logic=bin.logic; return(bin.retval); }
/*! Load, parse, and process a qdoc configuration file. This function is only called by the other load() function, but this one is recursive, i.e., it calls itself when it sees an \c{include} statement in the qdog configuration file. */ void Config::load(Location location, const QString& fileName) { QRegExp keySyntax("\\w+(?:\\.\\w+)*"); #define SKIP_CHAR() \ do { \ location.advance(c); \ ++i; \ c = text.at(i); \ cc = c.unicode(); \ } while (0) #define SKIP_SPACES() \ while (c.isSpace() && cc != '\n') \ SKIP_CHAR() #define PUT_CHAR() \ word += c; \ SKIP_CHAR(); if (location.depth() > 16) location.fatal(tr("Too many nested includes")); QFile fin(fileName); if (!fin.open(QFile::ReadOnly | QFile::Text)) { fin.setFileName(fileName + ".qdoc"); if (!fin.open(QFile::ReadOnly | QFile::Text)) location.fatal(tr("Cannot open file '%1': %2").arg(fileName).arg(fin.errorString())); } QString text = fin.readAll(); text += QLatin1String("\n\n"); text += QChar('\0'); fin.close(); location.push(fileName); location.start(); int i = 0; QChar c = text.at(0); uint cc = c.unicode(); while (i < (int) text.length()) { if (cc == 0) ++i; else if (c.isSpace()) { SKIP_CHAR(); } else if (cc == '#') { do { SKIP_CHAR(); } while (cc != '\n'); } else if (isMetaKeyChar(c)) { Location keyLoc = location; bool plus = false; QString stringValue; QStringList stringListValue; QString word; bool inQuote = false; bool prevWordQuoted = true; bool metWord = false; MetaStack stack; do { stack.process(c, location); SKIP_CHAR(); } while (isMetaKeyChar(c)); QStringList keys = stack.getExpanded(location); SKIP_SPACES(); if (keys.count() == 1 && keys.first() == "include") { QString includeFile; if (cc != '(') location.fatal(tr("Bad include syntax")); SKIP_CHAR(); SKIP_SPACES(); while (!c.isSpace() && cc != '#' && cc != ')') { includeFile += c; SKIP_CHAR(); } SKIP_SPACES(); if (cc != ')') location.fatal(tr("Bad include syntax")); SKIP_CHAR(); SKIP_SPACES(); if (cc != '#' && cc != '\n') location.fatal(tr("Trailing garbage")); /* Here is the recursive call. */ load(location, QFileInfo(QFileInfo(fileName).dir(), includeFile) .filePath()); } else { /* It wasn't an include statement, so it;s something else. */ if (cc == '+') { plus = true; SKIP_CHAR(); } if (cc != '=') location.fatal(tr("Expected '=' or '+=' after key")); SKIP_CHAR(); SKIP_SPACES(); for (;;) { if (cc == '\\') { int metaCharPos; SKIP_CHAR(); if (cc == '\n') { SKIP_CHAR(); } else if (cc > '0' && cc < '8') { word += QChar(c.digitValue()); SKIP_CHAR(); } else if ((metaCharPos = QString(QLatin1String("abfnrtv")).indexOf(c)) != -1) { word += "\a\b\f\n\r\t\v"[metaCharPos]; SKIP_CHAR(); } else { PUT_CHAR(); } } else if (c.isSpace() || cc == '#') { if (inQuote) { if (cc == '\n') location.fatal(tr("Unterminated string")); PUT_CHAR(); } else { if (!word.isEmpty()) { if (metWord) stringValue += QLatin1Char(' '); stringValue += word; stringListValue << word; metWord = true; word.clear(); prevWordQuoted = false; } if (cc == '\n' || cc == '#') break; SKIP_SPACES(); } } else if (cc == '"') { if (inQuote) { if (!prevWordQuoted) stringValue += QLatin1Char(' '); stringValue += word; if (!word.isEmpty()) stringListValue << word; metWord = true; word.clear(); prevWordQuoted = true; } inQuote = !inQuote; SKIP_CHAR(); } else if (cc == '$') { QString var; SKIP_CHAR(); while (c.isLetterOrNumber() || cc == '_') { var += c; SKIP_CHAR(); } if (!var.isEmpty()) { char *val = getenv(var.toLatin1().data()); if (val == 0) { location.fatal(tr("Environment variable '%1' undefined").arg(var)); } else { word += QString(val); } } } else { if (!inQuote && cc == '=') location.fatal(tr("Unexpected '='")); PUT_CHAR(); } } QStringList::ConstIterator key = keys.begin(); while (key != keys.end()) { if (!keySyntax.exactMatch(*key)) keyLoc.fatal(tr("Invalid key '%1'").arg(*key)); if (plus) { if (locMap[*key].isEmpty()) { locMap[*key] = keyLoc; } else { locMap[*key].setEtc(true); } if (stringValueMap[*key].isEmpty()) { stringValueMap[*key] = stringValue; } else { stringValueMap[*key] += QLatin1Char(' ') + stringValue; } stringListValueMap[*key] += stringListValue; } else { locMap[*key] = keyLoc; stringValueMap[*key] = stringValue; stringListValueMap[*key] = stringListValue; } ++key; } } } else { location.fatal(tr("Unexpected character '%1' at beginning of line") .arg(c)); } } }
bool PageGenerator::parseArg(const QString& src, const QString& tag, int* pos, int n, QStringRef* contents, QStringRef* par1, bool debug) { #define SKIP_CHAR(c) \ if (debug) \ qDebug() << "looking for " << c << " at " << QString(src.data() + i, n - i); \ if (i >= n || src[i] != c) { \ if (debug) \ qDebug() << " char '" << c << "' not found"; \ return false; \ } \ ++i; #define SKIP_SPACE \ while (i < n && src[i] == ' ') \ ++i; int i = *pos; int j = i; // assume "<@" has been parsed outside //SKIP_CHAR('<'); //SKIP_CHAR('@'); if (tag != QStringRef(&src, i, tag.length())) { if (0 && debug) qDebug() << "tag " << tag << " not found at " << i; return false; } if (debug) qDebug() << "haystack:" << src << "needle:" << tag << "i:" <<i; // skip tag i += tag.length(); // parse stuff like: linkTag("(<@link node=\"([^\"]+)\">).*(</@link>)"); if (par1) { SKIP_SPACE; // read parameter name j = i; while (i < n && src[i].isLetter()) ++i; if (src[i] == '=') { if (debug) qDebug() << "read parameter" << QString(src.data() + j, i - j); SKIP_CHAR('='); SKIP_CHAR('"'); // skip parameter name j = i; while (i < n && src[i] != '"') ++i; *par1 = QStringRef(&src, j, i - j); SKIP_CHAR('"'); SKIP_SPACE; } else { if (debug) qDebug() << "no optional parameter found"; } } SKIP_SPACE; SKIP_CHAR('>'); // find contents up to closing "</@tag> j = i; for (; true; ++i) { if (i + 4 + tag.length() > n) return false; if (src[i] != '<') continue; if (src[i + 1] != '/') continue; if (src[i + 2] != '@') continue; if (tag != QStringRef(&src, i + 3, tag.length())) continue; if (src[i + 3 + tag.length()] != '>') continue; break; } *contents = QStringRef(&src, j, i - j); i += tag.length() + 4; *pos = i; if (debug) qDebug() << " tag " << tag << " found: pos now: " << i; return true; #undef SKIP_CHAR }
/*! Load, parse, and process a qdoc configuration file. This function is only called by the other load() function, but this one is recursive, i.e., it calls itself when it sees an \c{include} statement in the qdoc configuration file. */ void Config::load(Location location, const QString& fileName) { QFileInfo fileInfo(fileName); QString path = fileInfo.canonicalPath(); pushWorkingDir(path); QDir::setCurrent(path); QRegExp keySyntax(QLatin1String("\\w+(?:\\.\\w+)*")); #define SKIP_CHAR() \ do { \ location.advance(c); \ ++i; \ c = text.at(i); \ cc = c.unicode(); \ } while (0) #define SKIP_SPACES() \ while (c.isSpace() && cc != '\n') \ SKIP_CHAR() #define PUT_CHAR() \ word += c; \ SKIP_CHAR(); if (location.depth() > 16) location.fatal(tr("Too many nested includes")); QFile fin(fileInfo.fileName()); if (!fin.open(QFile::ReadOnly | QFile::Text)) { if (!Config::installDir.isEmpty()) { int prefix = location.filePath().length() - location.fileName().length(); fin.setFileName(Config::installDir + QLatin1Char('/') + fileName.right(fileName.length() - prefix)); } if (!fin.open(QFile::ReadOnly | QFile::Text)) location.fatal(tr("Cannot open file '%1': %2").arg(fileName).arg(fin.errorString())); } QTextStream stream(&fin); #ifndef QT_NO_TEXTCODEC stream.setCodec("UTF-8"); #endif QString text = stream.readAll(); text += QLatin1String("\n\n"); text += QLatin1Char('\0'); fin.close(); location.push(fileName); location.start(); int i = 0; QChar c = text.at(0); uint cc = c.unicode(); while (i < (int) text.length()) { if (cc == 0) { ++i; } else if (c.isSpace()) { SKIP_CHAR(); } else if (cc == '#') { do { SKIP_CHAR(); } while (cc != '\n'); } else if (isMetaKeyChar(c)) { Location keyLoc = location; bool plus = false; QString stringValue; QStringList rhsValues; QString word; bool inQuote = false; bool prevWordQuoted = true; bool metWord = false; MetaStack stack; do { stack.process(c, location); SKIP_CHAR(); } while (isMetaKeyChar(c)); QStringList keys = stack.getExpanded(location); SKIP_SPACES(); if (keys.count() == 1 && keys.first() == QLatin1String("include")) { QString includeFile; if (cc != '(') location.fatal(tr("Bad include syntax")); SKIP_CHAR(); SKIP_SPACES(); while (!c.isSpace() && cc != '#' && cc != ')') { if (cc == '$') { QString var; SKIP_CHAR(); while (c.isLetterOrNumber() || cc == '_') { var += c; SKIP_CHAR(); } if (!var.isEmpty()) { const QByteArray val = qgetenv(var.toLatin1().data()); if (val.isNull()) { location.fatal(tr("Environment variable '%1' undefined").arg(var)); } else { includeFile += QString::fromLatin1(val); } } } else { includeFile += c; SKIP_CHAR(); } } SKIP_SPACES(); if (cc != ')') location.fatal(tr("Bad include syntax")); SKIP_CHAR(); SKIP_SPACES(); if (cc != '#' && cc != '\n') location.fatal(tr("Trailing garbage")); /* Here is the recursive call. */ load(location, QFileInfo(QDir(path), includeFile).filePath()); } else { /* It wasn't an include statement, so it's something else. We must see either '=' or '+=' next. If not, fatal error. */ if (cc == '+') { plus = true; SKIP_CHAR(); } if (cc != '=') location.fatal(tr("Expected '=' or '+=' after key")); SKIP_CHAR(); SKIP_SPACES(); for (;;) { if (cc == '\\') { int metaCharPos; SKIP_CHAR(); if (cc == '\n') { SKIP_CHAR(); } else if (cc > '0' && cc < '8') { word += QChar(c.digitValue()); SKIP_CHAR(); } else if ((metaCharPos = QString::fromLatin1("abfnrtv").indexOf(c)) != -1) { word += QLatin1Char("\a\b\f\n\r\t\v"[metaCharPos]); SKIP_CHAR(); } else { PUT_CHAR(); } } else if (c.isSpace() || cc == '#') { if (inQuote) { if (cc == '\n') location.fatal(tr("Unterminated string")); PUT_CHAR(); } else { if (!word.isEmpty()) { if (metWord) stringValue += QLatin1Char(' '); stringValue += word; #if 0 if (metWord) rhsValues << QString(" " + word); else #endif rhsValues << word; metWord = true; word.clear(); prevWordQuoted = false; } if (cc == '\n' || cc == '#') break; SKIP_SPACES(); } } else if (cc == '"') { if (inQuote) { if (!prevWordQuoted) stringValue += QLatin1Char(' '); stringValue += word; if (!word.isEmpty()) rhsValues << word; metWord = true; word.clear(); prevWordQuoted = true; } inQuote = !inQuote; SKIP_CHAR(); } else if (cc == '$') { QString var; SKIP_CHAR(); while (c.isLetterOrNumber() || cc == '_') { var += c; SKIP_CHAR(); } if (!var.isEmpty()) { const QByteArray val = qgetenv(var.toLatin1().constData()); if (val.isNull()) { location.fatal(tr("Environment variable '%1' undefined").arg(var)); } else { word += QString::fromLatin1(val); } } } else { if (!inQuote && cc == '=') location.fatal(tr("Unexpected '='")); PUT_CHAR(); } } QStringList::ConstIterator key = keys.constBegin(); while (key != keys.constEnd()) { if (!keySyntax.exactMatch(*key)) keyLoc.fatal(tr("Invalid key '%1'").arg(*key)); ConfigVarMultimap::Iterator i; i = configVars_.insert(*key, ConfigVar(*key, rhsValues, QDir::currentPath(), keyLoc)); i.value().plus_ = plus; ++key; } } } else { location.fatal(tr("Unexpected character '%1' at beginning of line").arg(c)); } } popWorkingDir(); if (!workingDirs_.isEmpty()) QDir::setCurrent(workingDirs_.top()); }