void parse() {
    char c = *input;
    printf("%c\n", c);

    if (isdigit(c) || c == '-') {
      parseNum();
    } else {
      char *s = (char*) malloc(4); strcpy(s, "111");
      bytecode::appendIntBytes(output, s);
      ++input;
    }
  
    /*
      if (isdigit(c) || c == '-') {
      parseNum();
      } else if (c == '[') {
      ++input; 
      // parseVec();
      } else if (c == '\'') {
      // parseStr();
      } else {
      char *s = (char*) malloc(4); strcpy(s, "111");
      bytecode::appendIntBytes(output, s);
      ++input;
      // parseSym();
      }
    */
  }
Beispiel #2
0
int parseNoSource(Spec spec, const char * field, rpmTag tag)
{
    const char *f, *fe;
    const char *name;
    rpmuint32_t num, flag;

    if (tag == RPMTAG_NOSOURCE) {
	flag = RPMFILE_SOURCE;
	name = "source";
    } else {
	flag = RPMFILE_PATCH;
	name = "patch";
    }
    
    fe = field;
    for (f = fe; *f != '\0'; f = fe) {
	struct Source *p;

	SKIPWHITE(f);
	if (*f == '\0')
	    break;
	fe = f;
	SKIPNONWHITE(fe);
	if (*fe != '\0') fe++;

	if (parseNum(f, &num)) {
	    rpmlog(RPMLOG_ERR, _("line %d: Bad number: %s\n"),
		     spec->lineNum, f);
	    return RPMRC_FAIL;
	}

	if (! (p = findSource(spec, num, flag))) {
	    rpmlog(RPMLOG_ERR, _("line %d: Bad no%s number: %d\n"),
		     spec->lineNum, name, num);
	    return RPMRC_FAIL;
	}

	p->flags |= RPMFILE_GHOST;

    }

    return RPMRC_OK;
}
Beispiel #3
0
					inline Val parseVal()
					{
						// Check value type
						switch(getC())
						{
							case '{': return parseObj();
							case '[': return parseArr();
							case '"': return parseStr();
							case 't': return parseBlnTrue();
							case 'f': return parseBlnFalse();
							case 'n': return parseNll();
						}

						// Check if value is a number
						if(isNumStart(getC())) return parseNum();

						throwError("Invalid value", std::string{"No match for values beginning with `"} + getC() + "`");

						return Val{Nll{}};
					}
Beispiel #4
0
Object* getObject(Value* value, VM* vm){
	Object* object = NULL;

	switch(value->type){
		case VALUE_TYPE_NULL:
			break;

		case VALUE_TYPE_NUM:
			object = pushInt(vm, parseNum(value->data, 10));
			break;

		case VALUE_TYPE_STRING:
			object = pushString(vm, parseString(value->data));
			break;

		case VALUE_TYPE_OP:
			break;

		case VALUE_TYPE_VAR:
			break;
	}

	return object;
}
Beispiel #5
0
int main (void) {
  // DECLARATIONS
  int flag;             /* equals 1 if a command is followed by '&' */
  char *args[MAX_LINE/2+1]; /* command line (of 80) must have < 40 arguments */ 
  int child,            /* process id of the child process */
    status,          /* result from execvp system call*/
    length, // size of inputBuffer[]
    temp, // for char->int conversion
    i, j, // indices
    illegal, // boolean for illegal history call
    historyNum, // stores cmd called in historyBuffer
    offset, // difference between historyNum and historyIndex
    historyIndex; // stores index (0-9) corresponding to command #historyNum
  char inputBuffer[MAX_LINE], test;   /* buffer to hold the command entered */
  
  // INITIALIZATIONS
  cmdCount = 0;
  illegal = 0;
  signal(SIGINT, shellHandler);

  while (1) {            /* Program terminates normally inside setup */
    flag = 0;
    rls = 0;
    printf("Input Command:\n"); // read input
    length = read(0,inputBuffer,MAX_LINE); 
    
    if (inputBuffer[0] == '!') { // if it's a call to historyBuffer (handle "!..."
      // validate input
      if (length > 2) {
	// determine number after '!' (cmd to run)
	if (length == 3 && inputBuffer[1] == '!') { // run last command
	  if(cmdCount == 0) {
	    printf("ERROR: You haven't put in any commands yet! Try again.\n");
	    continue;
	  }
	  historyNum = cmdCount;
	}
	else historyNum = parseNum(inputBuffer);
	historyNum--; // because array starts at 0, not 1
	if (historyNum < 0 || historyNum < cmdCount-11 || historyNum > cmdCount-1){
	  printf("ERROR: command called (#%d) is out of historyBuffer's range! Please try again.\n", historyNum+1); // +1 to account for offset
	  illegal = 1;
	  continue; // restart while loop
	}
	// find index in historyBuffer corresponding to historyNum
	if (cmdCount > 10){
	  offset = cmdCount-10;
	  historyIndex = historyNum - offset;
	} else historyIndex = historyNum;
	getInput(historyIndex, inputBuffer);
	temp = length;
	length = getLength(historyIndex); // update length
	for(i=0; i<length; i++) printf("%c", inputBuffer[i]);
	printf("\n");
      }
    } // end if for '!...'

    // add command to historyBuffer
    if (cmdCount < 10) {
      for (i=0; i<length; i++){
	     historyBuffer[cmdCount][i] = inputBuffer[i];
      } // end for
      cmdCount++;
    } // end if
    else { // >10 commands
      for (i=1; i < 10; i++) { // make room for new command (delete row 0)
	     for (j=0; historyBuffer[i][j] != '\n'; j++){
	       historyBuffer[i-1][j] = historyBuffer[i][j];
	     }
	     historyBuffer[i-1][j] = '\n'; // append '\n'
      } // end for
      for (i=0; i<length; i++)
	historyBuffer[9][i] = inputBuffer[i];
      cmdCount++;
    } // end else

    if (inputBuffer[0] == 'R' && inputBuffer[1] == 'L' && inputBuffer[2] == 'S') // handle RLS
      rls = 1; // flip RLS flag
    printf("Length = %d\n", length);

    setup(inputBuffer,args,&flag,length);       /* get next command */ // send command to setup()

    if ((illegal == 0 || illegal == 1) && rls == 0) { // check for illegal history call, temporarily nullified
      child = fork();          /* creates a duplicate process! */
      switch (child) {
	
      case -1: 
	perror("could not fork the process");
	break; /* perror is a library routine that displays a system
		  error message, according to the value of the system
		  variable "errno" which will be set during a function 
		  (like fork) that was unable to successfully
		  complete its task. */
	
      case 0: /* here is the child process */
	status = execvp(args[0],args);
	if (status != 0){
	  perror("Error in execvp!");
	  exit(-2); /* terminate this process with error code -2 */
	}
	break;
	
      default : 
	if(flag==0) /* handle parent, wait for child */
	  while (child != wait((int *) 0)) ;
	
      } // end switch
    } // end if
  } // end big while
} // end main
Beispiel #6
0
static usize_t dc(String* args) {
	int stack[10];
	signed char index = -1;
	String input;
	String badSyntax = newstr("Bad syntax", 10);
	String lackData = newstr("Stack empty", 11);
	String notANumber = newstr("Not a number", 12);
	while (1) {
		get(&input);
		if ((input.str[0] >= '0' && input.str[0] <= '9')
		  || input.str[0] == '-') {
			if(parseNum(&input, stack + index + 1)) {
				println(notANumber);
			}
			else {
				index++;
			}
		}
		else if (input.size == 1) {
			switch(input.str[0]) {
				case '+': if (index >= 1) {
						stack[index - 1] = stack[index - 1] + stack[index];
						index--;
					}
					else {
						println(lackData);
					}
					break;
				case '-': if (index >= 1) {
						stack[index - 1] = stack[index - 1] - stack[index];
						index--;
					}
					else {
						println(lackData);
					}
					break;
				case '*': if (index >= 1) {
						stack[index - 1] = stack[index - 1] * stack[index];
						index--;
					}
					else {
						println(lackData);
					}
					break;
				case '/': if (index >= 1) {
						stack[index - 1] = stack[index - 1] / stack[index];
						index--;
					}
					else {
						println(lackData);
					}
					break;
				case '%': if (index >= 1) {
						stack[index - 1] = stack[index - 1] % stack[index];
						index--;
					}
					else {
						println(lackData);
					}
					break;
				case 'p': if (index >= 0) {
						printNum(stack[index]);
					}
					break;
				case 'c': index = -1;
					break;
				case 'q': return 0;
				default:
					println(badSyntax);
			}
		}
		else {
			println(badSyntax);
		}
	}
}
Beispiel #7
0
Value* Value_next(const char** expr, char end, parser_cb* cb) {
	Value* ret;
	
	trimSpaces(expr);
	if(**expr == end) {
		return ValEnd();
	}
	
	if(getSign(expr) == -1) {
		return ValNeg();
	}
	
	trimSpaces(expr);
	
	
	if(isdigit(**expr) || **expr == '.') {
		ret = parseNum(expr);
	}
	else if(**expr == '(') {
		(*expr)++;
		ret = Value_parse(expr, 0, ')', cb);
	}
	else if(**expr == '<') {
		(*expr)++;
		ret = Vector_parse(expr, cb);
	}
	else if(**expr == '|') {
		(*expr)++;
		Value* val = Value_parse(expr, 0, '|', cb);
		
		/* Error checking */
		if(val->type == VAL_ERR) {
			return val;
		}
		
		/* Use absolute value builtin */
		TP(tp);
		ret = TP_FILL(tp, "@abs(@@)", val);
	}
	else if(**expr == '@') {
		/* Invoke callback to handle special value */
		ret = cb->func(expr, cb->data);
	}
	else {
		ret = parseToken(expr, cb);
	}
	
	/* Check if a parse error occurred */
	if(ret->type == VAL_ERR) {
		return ret;
	}
	
	while(1) {
		bool again = true;
		Value* tmp = NULL;
		
		trimSpaces(expr);
		switch(**expr) {
			case '[':
				tmp = subscriptVector(ret, expr, cb);
				break;
			
			case '(':
				tmp = callFunc(ret, expr, cb);
				break;
			
			default:
				again = false;
				break;
		}
		
		if(!again || tmp == ret) {
			break;
		}
		
		if(tmp->type == VAL_ERR) {
			return tmp;
		}
		
		ret = tmp;
	}
	
	/* Check for unary signs afterwards */
	while(**expr == '!') {
		(*expr)++;
		trimSpaces(expr);
		ret = ValUnary(UnOp_new(UN_FACT, ret));
	}

	return ret;
}
Beispiel #8
0
/**
 * Parse %patch line.
 * @param spec		build info
 * @param line		current line from spec file
 * @return		RPMRC_OK on success
 */
static rpmRC doPatchMacro(Spec spec, const char * line)
	/*@globals rpmGlobalMacroContext, h_errno,
		fileSystem, internalState @*/
	/*@modifies spec->prep, rpmGlobalMacroContext,
		fileSystem, internalState  @*/
{
    char *s;
    char *opt_b;
    char *opt_d;
    rpmuint32_t opt_P, opt_p, opt_R, opt_E, opt_F;
    char buf[BUFSIZ], *bp;
    rpmuint32_t patch_nums[1024];  /* XXX - we can only handle 1024 patches! */
    int patch_index, x;

    memset(patch_nums, 0, sizeof(patch_nums));
    opt_P = opt_p = opt_R = opt_E = 0;
    opt_F = rpmExpandNumeric("%{?_default_patch_fuzz}%{!?_default_patch_fuzz:-1}");
    opt_b = NULL;
    opt_d = NULL;
    patch_index = 0;

    if (! strchr(" \t\n", line[6])) {
	/* %patchN */
	sprintf(buf, "%%patch -P %s", line + 6);
    } else {
	strncpy(buf, line, sizeof(buf)-1);
	buf[sizeof(buf)-1] = '\0';
    }

    /*@-internalglobs@*/	/* FIX: strtok has state */
    for (bp = buf; (s = strtok(bp, " \t\n")) != NULL;) {
	if (bp) {	/* remove 1st token (%patch) */
	    bp = NULL;
	    continue;
	}
	if (!strcmp(s, "-P")) {
	    opt_P = 1;
	} else if (!strcmp(s, "-R")) {
	    opt_R = 1;
	} else if (!strcmp(s, "-E")) {
	    opt_E = 1;
	} else if (!strcmp(s, "-b")) {
	    /* orig suffix */
	    opt_b = strtok(NULL, " \t\n");
	    if (! opt_b) {
		rpmlog(RPMLOG_ERR,
			_("line %d: Need arg to %%patch -b: %s\n"),
			spec->lineNum, spec->line);
		return RPMRC_FAIL;
	    }
	} else if (!strcmp(s, "-z")) {
	    /* orig suffix */
	    opt_b = strtok(NULL, " \t\n");
	    if (! opt_b) {
		rpmlog(RPMLOG_ERR,
			_("line %d: Need arg to %%patch -z: %s\n"),
			spec->lineNum, spec->line);
		return RPMRC_FAIL;
	    }
	} else if (!strcmp(s, "-F")) {
	    /* fuzz factor */
	    const char * fnum = (!strchr(" \t\n", s[2])
				? s+2 : strtok(NULL, " \t\n"));
	    char * end = NULL;

	    opt_F = (fnum ? strtol(fnum, &end, 10) : 0);
	    if (! opt_F || *end) {
		rpmlog(RPMLOG_ERR,
			_("line %d: Bad arg to %%patch -F: %s\n"),
			spec->lineNum, spec->line);
		return RPMRC_FAIL;
	    }
	} else if (!strcmp(s, "-d")) {
	    /* subdirectory */
	    opt_d = strtok(NULL, " \t\n");
	    if (! opt_d) {
		rpmlog(RPMLOG_ERR,
			_("line %d: Need arg to %%patch -d: %s\n"),
			spec->lineNum, spec->line);
		return RPMRC_FAIL;
	    }
	} else if (!strncmp(s, "-p", sizeof("-p")-1)) {
	    /* unfortunately, we must support -pX */
	    if (! strchr(" \t\n", s[2])) {
		s = s + 2;
	    } else {
		s = strtok(NULL, " \t\n");
		if (s == NULL) {
		    rpmlog(RPMLOG_ERR,
			     _("line %d: Need arg to %%patch -p: %s\n"),
			     spec->lineNum, spec->line);
		    return RPMRC_FAIL;
		}
	    }
	    if (parseNum(s, &opt_p)) {
		rpmlog(RPMLOG_ERR,
			_("line %d: Bad arg to %%patch -p: %s\n"),
			spec->lineNum, spec->line);
		return RPMRC_FAIL;
	    }
	} else {
	    /* Must be a patch num */
	    if (patch_index == 1024) {
		rpmlog(RPMLOG_ERR, _("Too many patches!\n"));
		return RPMRC_FAIL;
	    }
	    if (parseNum(s, &(patch_nums[patch_index]))) {
		rpmlog(RPMLOG_ERR, _("line %d: Bad arg to %%patch: %s\n"),
			 spec->lineNum, spec->line);
		return RPMRC_FAIL;
	    }
	    patch_index++;
	}
    }
    /*@=internalglobs@*/

    /* All args processed */

    if (! opt_P) {
	s = doPatch(spec, 0, opt_p, opt_b, opt_R, opt_E, opt_F, opt_d);
	if (s == NULL)
	    return RPMRC_FAIL;
	spec->prep = rpmiobAppend(spec->prep, s, 1);
    }

    for (x = 0; x < patch_index; x++) {
	s = doPatch(spec, patch_nums[x], opt_p, opt_b, opt_R, opt_E, opt_F, opt_d);
	if (s == NULL)
	    return RPMRC_FAIL;
	spec->prep = rpmiobAppend(spec->prep, s, 1);
    }

    return RPMRC_OK;
}
Beispiel #9
0
/**
 * Parse %setup macro.
 * @todo FIXME: Option -q broken when not immediately after %setup.
 * @param spec		build info
 * @param line		current line from spec file
 * @return		0 on success
 */
static int doSetupMacro(Spec spec, const char * line)
	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
	/*@modifies spec->buildSubdir, spec->macros, spec->prep,
		spec->packages->header,
		rpmGlobalMacroContext, fileSystem, internalState @*/
{
    char buf[BUFSIZ];
    rpmiob before = NULL;
    rpmiob after = NULL;
    poptContext optCon;
    int argc;
    const char ** argv;
    int arg;
    const char * optArg;
    int rc;
    rpmuint32_t num;
    rpmRC ec = RPMRC_FAIL;	/* XXX assume failure */

    /*@-mods@*/
    leaveDirs = skipDefaultAction = 0;
    createDir = quietly = 0;
    dirName = NULL;
    /*@=mods@*/

    if ((rc = poptParseArgvString(line, &argc, &argv))) {
	rpmlog(RPMLOG_ERR, _("Error parsing %%setup: %s\n"),
			poptStrerror(rc));
	goto exit;
    }

    before = rpmiobNew(0);
    after = rpmiobNew(0);

    optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
    while ((arg = poptGetNextOpt(optCon)) > 0) {
	optArg = poptGetOptArg(optCon);

	/* We only parse -a and -b here */

	if (parseNum(optArg, &num)) {
	    rpmlog(RPMLOG_ERR, _("line %d: Bad arg to %%setup: %s\n"),
		     spec->lineNum, (optArg ? optArg : "???"));
	    optCon = poptFreeContext(optCon);
	    argv = _free(argv);
	    goto exit;
	}

	{   const char *chptr = doUntar(spec, num, quietly);
	    if (chptr == NULL)
		goto exit;

	    (void) rpmiobAppend((arg == 'a' ? after : before), chptr, 1);
	}
    }

    if (arg < -1) {
	rpmlog(RPMLOG_ERR, _("line %d: Bad %%setup option %s: %s\n"),
		 spec->lineNum,
		 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
		 poptStrerror(arg));
	optCon = poptFreeContext(optCon);
	argv = _free(argv);
	goto exit;
    }

    if (dirName) {
	spec->buildSubdir = xstrdup(dirName);
    } else {
	const char *N, *V;
	(void) headerNEVRA(spec->packages->header, &N, NULL, &V, NULL, NULL);
	(void) snprintf(buf, sizeof(buf), "%s-%s", N, V);
	buf[sizeof(buf)-1] = '\0';
	N = _free(N);
	V = _free(V);
	spec->buildSubdir = xstrdup(buf);
    }
    addMacro(spec->macros, "buildsubdir", NULL, spec->buildSubdir, RMIL_SPEC);

    optCon = poptFreeContext(optCon);
    argv = _free(argv);

    /* cd to the build dir */
    {	const char * buildDirURL = rpmGenPath(spec->rootURL, "%{_builddir}", "");
	const char *buildDir;

	(void) urlPath(buildDirURL, &buildDir);
	rc = rpmioMkpath(buildDir, 0755, -1, -1);
	sprintf(buf, "cd '%s'", buildDir);
	spec->prep = rpmiobAppend(spec->prep, buf, 1);
	buildDirURL = _free(buildDirURL);
    }

    /* delete any old sources */
    if (!leaveDirs) {
	sprintf(buf, "rm -rf '%s'", spec->buildSubdir);
	spec->prep = rpmiobAppend(spec->prep, buf, 1);
    }

    /* check if source is a ruby gem */
    {   struct Source *sp;
	for (sp = spec->sources; sp != NULL; sp = sp->next) {
	    if ((sp->flags & RPMFILE_SOURCE) && (sp->num == 0)) {
		break;
	    }
	}
	if (sp != NULL) {
	    char *t = strrchr(sp->source, '.');
	    if(t && !strcasecmp(t, ".gem"))
		createDir = 1;
	}
    }

    /* if necessary, create and cd into the proper dir */
    if (createDir) {
	char *mkdir_p;
	mkdir_p = rpmExpand("%{?__mkdir_p}%{!?__mkdir_p:mkdir -p}", NULL);
	if (!mkdir_p)
	    mkdir_p = xstrdup("mkdir -p");
	sprintf(buf, "%s '%s'\ncd '%s'",
		mkdir_p, spec->buildSubdir, spec->buildSubdir);
	mkdir_p = _free(mkdir_p);
	spec->prep = rpmiobAppend(spec->prep, buf, 1);
    }

    /* do the default action */
   if (!createDir && !skipDefaultAction) {
	const char *chptr = doUntar(spec, 0, quietly);
	if (chptr == NULL)
	    goto exit;
	spec->prep = rpmiobAppend(spec->prep, chptr, 1);
    }

    spec->prep = rpmiobAppend(spec->prep, rpmiobStr(before), 0);

    if (!createDir) {
	sprintf(buf, "cd '%s'", spec->buildSubdir);
	spec->prep = rpmiobAppend(spec->prep, buf, 1);
    }

    if (createDir && !skipDefaultAction) {
	const char * chptr = doUntar(spec, 0, quietly);
	if (chptr == NULL)
	    goto exit;
	spec->prep = rpmiobAppend(spec->prep, chptr, 1);
    }

    spec->prep = rpmiobAppend(spec->prep, rpmiobStr(after), 0);

    /* XXX FIXME: owner & group fixes were conditioned on !geteuid() */
    /* Fix the owner, group, and permissions of the setup build tree */
    {	/*@observer@*/ static const char *fixmacs[] =
		{ "%{_fixowner}", "%{_fixgroup}", "%{_fixperms}", NULL };
	const char ** fm;

	for (fm = fixmacs; *fm; fm++) {
	    const char *fix;
	    fix = rpmExpand(*fm, " .", NULL);
	    if (fix && *fix != '%')
		spec->prep = rpmiobAppend(spec->prep, fix, 1);
	    fix = _free(fix);
	}
    }
    ec = RPMRC_OK;

exit:
    before = rpmiobFree(before);
    after = rpmiobFree(after);
    return ec;
}
Beispiel #10
0
/*Multiply the numbers*/
void mult(char* number1, char* number2, char* outbase){
	struct number *num1 = parseNum(number1);
	struct number *num2 = parseNum(number2);

}
Beispiel #11
0
static rpmRC handlePreambleTag(Spec spec, Package pkg, rpmTag tag,
		const char *macro, const char *lang)
	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
	/*@modifies spec->macros, spec->st,
		spec->sources, spec->numSources, spec->noSource,
		spec->sourceHeader, spec->BANames, spec->BACount,
		spec->line,
		pkg->header, pkg->autoProv, pkg->autoReq, pkg->noarch,
		rpmGlobalMacroContext, fileSystem, internalState @*/
{
    HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    char * field = spec->line;
    char * end;
    int multiToken = 0;
    rpmsenseFlags tagflags;
    int len;
    rpmuint32_t num;
    int rc;
    int xx;
    
    if (field == NULL) return RPMRC_FAIL;	/* XXX can't happen */
    /* Find the start of the "field" and strip trailing space */
    while ((*field) && (*field != ':'))
	field++;
    if (*field != ':') {
	rpmlog(RPMLOG_ERR, _("line %d: Malformed tag: %s\n"),
		 spec->lineNum, spec->line);
	return RPMRC_FAIL;
    }
    field++;
    SKIPSPACE(field);
    if (!*field) {
	/* Empty field */
	rpmlog(RPMLOG_ERR, _("line %d: Empty tag: %s\n"),
		 spec->lineNum, spec->line);
	return RPMRC_FAIL;
    }
    end = findLastChar(field);

    /* Validate tag data content. */
    if (tagValidate(spec, tag, field) != RPMRC_OK)
	return RPMRC_FAIL;

    /* See if this is multi-token */
    end = field;
    SKIPNONSPACE(end);
    if (*end != '\0')
	multiToken = 1;

    switch (tag) {
    case RPMTAG_NAME:
    case RPMTAG_VERSION:
    case RPMTAG_RELEASE:
    case RPMTAG_DISTEPOCH:
    case RPMTAG_URL:
    case RPMTAG_DISTTAG:
    case RPMTAG_REPOTAG:
    case RPMTAG_CVSID:
    case RPMTAG_BUGURL:
	SINGLE_TOKEN_ONLY;
	/* These macros are for backward compatibility */
	if (tag == RPMTAG_VERSION) {
	    if (strchr(field, '-') != NULL) {
		rpmlog(RPMLOG_ERR, _("line %d: Illegal char '-' in %s: %s\n"),
		    spec->lineNum, "version", spec->line);
		return RPMRC_FAIL;
	    }
	    addMacro(spec->macros, "PACKAGE_VERSION", NULL, field, RMIL_OLDSPEC);
	} else if (tag == RPMTAG_RELEASE) {
	    if (strchr(field, '-') != NULL) {
		rpmlog(RPMLOG_ERR, _("line %d: Illegal char '-' in %s: %s\n"),
		    spec->lineNum, "release", spec->line);
		return RPMRC_FAIL;
	    }
	    addMacro(spec->macros, "PACKAGE_RELEASE", NULL, field, RMIL_OLDSPEC-1);
	}
	he->tag = tag;
	he->t = RPM_STRING_TYPE;
	he->p.str = field;
	he->c = 1;
	xx = headerPut(pkg->header, he, 0);
	break;
    case RPMTAG_GROUP:
    case RPMTAG_SUMMARY:
#if defined(RPM_VENDOR_OPENPKG) /* make-class-available-as-macro */
    case RPMTAG_CLASS:
#endif
	(void) stashSt(spec, pkg->header, tag, lang);
	/*@fallthrough@*/
    case RPMTAG_DISTRIBUTION:
    case RPMTAG_VENDOR:
    case RPMTAG_LICENSE:
    case RPMTAG_PACKAGER:
	if (!*lang) {
	    he->tag = tag;
	    he->t = RPM_STRING_TYPE;
	    he->p.str = field;
	    he->c = 1;
	    xx = headerPut(pkg->header, he, 0);
	} else if (!(noLang && strcmp(lang, RPMBUILD_DEFAULT_LANG))) {
	    (void) headerAddI18NString(pkg->header, tag, field, lang);
	}
	break;
    /* XXX silently ignore BuildRoot: */
    case RPMTAG_BUILDROOT:
	SINGLE_TOKEN_ONLY;
	macro = NULL;
#ifdef	DYING
	buildRootURL = rpmGenPath(spec->rootURL, "%{?buildroot}", NULL);
	(void) urlPath(buildRootURL, &buildRoot);
	if (*buildRoot == '\0') buildRoot = "/";
	if (!strcmp(buildRoot, "/")) {
	    rpmlog(RPMLOG_ERR,
		     _("BuildRoot can not be \"/\": %s\n"), spec->buildRootURL);
	    buildRootURL = _free(buildRootURL);
	    return RPMRC_FAIL;
	}
	buildRootURL = _free(buildRootURL);
#endif
	break;
    case RPMTAG_KEYWORDS:
    case RPMTAG_VARIANTS:
    case RPMTAG_PREFIXES:
	addOrAppendListEntry(pkg->header, tag, field);
	he->tag = tag;
	xx = headerGet(pkg->header, he, 0);
	if (tag == RPMTAG_PREFIXES)
	while (he->c--) {
	    if (he->p.argv[he->c][0] != '/') {
		rpmlog(RPMLOG_ERR,
			 _("line %d: Prefixes must begin with \"/\": %s\n"),
			 spec->lineNum, spec->line);
		he->p.ptr = _free(he->p.ptr);
		return RPMRC_FAIL;
	    }
	    len = (int)strlen(he->p.argv[he->c]);
	    if (he->p.argv[he->c][len - 1] == '/' && len > 1) {
		rpmlog(RPMLOG_ERR,
			 _("line %d: Prefixes must not end with \"/\": %s\n"),
			 spec->lineNum, spec->line);
		he->p.ptr = _free(he->p.ptr);
		return RPMRC_FAIL;
	    }
	}
	he->p.ptr = _free(he->p.ptr);
	break;
    case RPMTAG_DOCDIR:
	SINGLE_TOKEN_ONLY;
	if (field[0] != '/') {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: Docdir must begin with '/': %s\n"),
		     spec->lineNum, spec->line);
	    return RPMRC_FAIL;
	}
	macro = NULL;
	delMacro(NULL, "_docdir");
	addMacro(NULL, "_docdir", NULL, field, RMIL_SPEC);
	break;
    case RPMTAG_XMAJOR:
    case RPMTAG_XMINOR:
    case RPMTAG_EPOCH:
	SINGLE_TOKEN_ONLY;
	if (parseNum(field, &num)) {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: %s takes an integer value: %s\n"),
		     spec->lineNum, tagName(tag), spec->line);
	    return RPMRC_FAIL;
	}
	he->tag = tag;
	he->t = RPM_UINT32_TYPE;
	he->p.ui32p = &num;
	he->c = 1;
	xx = headerPut(pkg->header, he, 0);
	break;
    case RPMTAG_AUTOREQPROV:
	pkg->autoReq = parseYesNo(field);
	pkg->autoProv = pkg->autoReq;
	break;
    case RPMTAG_AUTOREQ:
	pkg->autoReq = parseYesNo(field);
	break;
    case RPMTAG_AUTOPROV:
	pkg->autoProv = parseYesNo(field);
	break;
    case RPMTAG_SOURCE:
    case RPMTAG_PATCH:
	SINGLE_TOKEN_ONLY;
	macro = NULL;
	if ((rc = addSource(spec, pkg, field, tag)))
	    return rc;
	break;
    case RPMTAG_ICON:
	SINGLE_TOKEN_ONLY;
	macro = NULL;
	if ((rc = addSource(spec, pkg, field, tag)))
	    return rc;
	/* XXX the fetch/load of icon needs to be elsewhere. */
	if ((rc = doIcon(spec, pkg->header)))
	    return rc;
	break;
    case RPMTAG_NOSOURCE:
    case RPMTAG_NOPATCH:
	spec->noSource = 1;
	if ((rc = parseNoSource(spec, field, tag)))
	    return rc;
	break;
    case RPMTAG_BUILDPREREQ:
    case RPMTAG_BUILDREQUIRES:
	if ((rc = parseBits(lang, buildScriptBits, &tagflags))) {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: Bad %s: qualifiers: %s\n"),
		     spec->lineNum, tagName(tag), spec->line);
	    return rc;
	}
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    case RPMTAG_PREREQ:
    case RPMTAG_REQUIREFLAGS:
	if ((rc = parseBits(lang, installScriptBits, &tagflags))) {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: Bad %s: qualifiers: %s\n"),
		     spec->lineNum, tagName(tag), spec->line);
	    return rc;
	}
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    /* Aliases for BuildRequires(hint): */
    case RPMTAG_BUILDSUGGESTS:
    case RPMTAG_BUILDENHANCES:
	tagflags = RPMSENSE_MISSINGOK;
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    /* Aliases for Requires(hint): */
    case RPMTAG_SUGGESTSFLAGS:
    case RPMTAG_ENHANCESFLAGS:
	tag = RPMTAG_REQUIREFLAGS;
	tagflags = RPMSENSE_MISSINGOK;
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    case RPMTAG_BUILDOBSOLETES:
    case RPMTAG_BUILDPROVIDES:
    case RPMTAG_BUILDCONFLICTS:
    case RPMTAG_CONFLICTFLAGS:
    case RPMTAG_OBSOLETEFLAGS:
    case RPMTAG_PROVIDEFLAGS:
	tagflags = RPMSENSE_ANY;
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    case RPMTAG_BUILDPLATFORMS:		/* XXX needs pattern parsing */
    case RPMTAG_EXCLUDEARCH:
    case RPMTAG_EXCLUSIVEARCH:
    case RPMTAG_EXCLUDEOS:
    case RPMTAG_EXCLUSIVEOS:
	addOrAppendListEntry(spec->sourceHeader, tag, field);
	break;

    case RPMTAG_BUILDARCHS:
    {	const char ** BANames = NULL;
	int BACount = 0;
	if ((rc = poptParseArgvString(field, &BACount, &BANames))) {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: Bad BuildArchitecture format: %s\n"),
		     spec->lineNum, spec->line);
	    return RPMRC_FAIL;
	}
	if (spec->toplevel) {
	    if (BACount > 0 && BANames != NULL) {
		spec->BACount = BACount;
		spec->BANames = BANames;
		BANames = NULL;		/* XXX don't free. */
	    }
	} else {
	    if (BACount != 1 || strcmp(BANames[0], "noarch")) {
		rpmlog(RPMLOG_ERR,
		     _("line %d: Only \"noarch\" sub-packages are supported: %s\n"),
		     spec->lineNum, spec->line);
		BANames = _free(BANames);
		return RPMRC_FAIL;
	    }
	    pkg->noarch = 1;
	}
	BANames = _free(BANames);
    }	break;

    default:
	macro = NULL;
	he->tag = tag;
	he->t = RPM_STRING_ARRAY_TYPE;
	he->p.argv= (const char **) &field;	/* XXX NOCAST */
	he->c = 1;
	he->append = 1;
	xx = headerPut(pkg->header, he, 0);
	he->append = 0;
	break;
    }

/*@-usereleased@*/
    if (macro)
	addMacro(spec->macros, macro, NULL, field, RMIL_SPEC);
/*@=usereleased@*/
    
    return RPMRC_OK;
}