tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: bin/41700: :tr modifier for NetBSD make [patch]
I move this discussion to the mailing list.
> Some comments about the code....
> (NB not about whether this is a good idea)
>
>> +static char *
>> +VarTranslate(char *str, char *chars, char *repl)
>> +{
>> + Buffer buf;
>> + int table [UCHAR_MAX+1];
>> + int r;
>> + int c;
>> +
>> + /* initialization of translation table */
>> + memset (table, -1, sizeof (table));
>
> initialize table[n] = n here, table can then be char.
Ok.
>> + for (; *chars; ++chars, ++repl){
>> + assert (*repl != 0);
>
> Don't assert! I can't remember what tr(1) does, but terminating
> the action wouldn't be too bad.
>
>> + table [(unsigned char) *chars] = (unsigned char) *repl;
>
> You need to support ranges!
Do others also think ranges are really necessary? I my view this rarely
used feature (:tu and :tl are already implemented) adds unnecessary
complexity to the code and makes bmake Makefiles dependent on ASCII
(remember EBCDIC). Inventing character classes for :tr adds yet another
unnecessary bloat... I'd prefer not to add ranges.
>> + }
>> + assert (*repl == 0);
>> +
>> + /* translation */
>
> Don't use 'buf', just tgt = malloc(strlen(str) + 1)
Ok.
>> + Buf_Init(&buf, 0);
>> + for (; *str ; ++str) {
>> + c = (unsigned char) *str;
>> + r = table [c];
>> + if (r == -1)
>> + Buf_AddByte(&buf, (Byte)c);
>> + else
>> + Buf_AddByte(&buf, (Byte)r);
>> + }
>> + Buf_AddByte(&buf, (Byte)'\0');
> In any case Buf_Addbyte guarantees \0 terminated
Ok.
>> + str = (char *)Buf_GetAll(&buf, NULL);
>> + Buf_Destroy(&buf, FALSE);
>> + return str;
>> +}
>> +
>> +/*-
>> + *-----------------------------------------------------------------------
>> * VarChangeCase --
>> * Change the string to all uppercase or all lowercase
>> *
>> @@ -2655,7 +2707,47 @@
>> case 't':
>> {
>> cp = tstr + 1; /* make sure it is set */
>> - if (tstr[1] != endc && tstr[1] != ':') {
>> + if (tstr[1] == 'r') {
>> + char *chars, *repl;
>> + int chars_len, repl_len;
>> +
>> + delim = tstr[2];
>> + tstr += 3;
>> +
>> + cp = tstr;
>> + chars = VarGetPattern(
>> + ctxt, &parsestate, errnum,
>> + &cp, delim, NULL,
>> + &chars_len,
>> + NULL);
>> + if (!chars)
>> + goto cleanup;
>> +
>> + repl = VarGetPattern(
>> + ctxt, &parsestate, errnum,
>> + &cp, delim, NULL,
>> + &repl_len,
>> + NULL);
>> + if (!repl)
>> + goto cleanup;
>> +
>> + delim = '\0';
>
> No need to do the check below twice!
Do you mean assert(3)s?
>> + if (strlen (chars) != strlen (repl)){
>> + free(chars);
>> + free(repl);
>> +
>> + Error("Bad arguments for :tr modifier for variable %s",
>> + v->name);
>> + goto cleanup;
>> + }
>> +
>> + termc = *cp;
>> + newStr = VarTranslate(nstr, chars, repl);
>> +
>> + free(chars);
>> + free(repl);
>> + }else if (tstr[1] != endc && tstr[1] != ':') {
>> if (tstr[1] == 's') {
>> /*
>> * Use the char (if any) at tstr[2]
>>
--
Best regards, Aleksey Cheusov.
Home |
Main Index |
Thread Index |
Old Index