Skip to content

Commit

Permalink
[builtin/printf] Support %()T
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed Mar 18, 2020
1 parent 0ff0a74 commit 44d5af8
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 8 deletions.
4 changes: 2 additions & 2 deletions frontend/lexer_def.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,8 +535,8 @@ def IsKeyword(name):
R('[1-9][0-9]*', Id.Format_Num),
C('.', Id.Format_Dot),
# We support dsq. The others we parse to display an error message.
R('[disqbcouxXeEfFgG]', Id.Format_Type),
R(r'[^\0]', Id.Unknown_Tok), # any otehr char
R('[disqbcouxXeEfFgG]|\([^()]*\)T', Id.Format_Type),
R(r'[^\0]', Id.Unknown_Tok), # any other char
]

LEXER_DEF[lex_mode_e.VSub_1] = [
Expand Down
27 changes: 24 additions & 3 deletions osh/builtin_printf.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
from __future__ import print_function

from _devbuild.gen.id_kind_asdl import Id, Kind
from _devbuild.gen.runtime_asdl import cmd_value__Argv
from _devbuild.gen.runtime_asdl import cmd_value__Argv, value_e, value__Str
from _devbuild.gen.syntax_asdl import (
printf_part, printf_part_t,
source
)
from _devbuild.gen.types_asdl import lex_mode_e, lex_mode_t

import sys
import time
import os

from asdl import runtime
from core import error
Expand All @@ -27,7 +29,7 @@
from osh import string_ops
from osh import word_compile

from typing import Dict, List, TYPE_CHECKING
from typing import Dict, List, TYPE_CHECKING, cast

if TYPE_CHECKING:
from frontend.lexer import Lexer
Expand All @@ -40,6 +42,7 @@
PRINTF_SPEC = arg_def.Register('printf') # TODO: Don't need this?
PRINTF_SPEC.ShortFlag('-v', args.Str)

shell_start_time = time.time()

class _FormatStringParser(object):
"""
Expand Down Expand Up @@ -219,14 +222,16 @@ def Run(self, cmd_val):
s = s[:precision] # truncate
elif typ == 'q':
s = string_ops.ShellQuoteOneLine(s)
elif typ in 'diouxX':
elif typ in 'diouxX' or typ.endswith('T'):
try:
d = int(s)
except ValueError:
if len(s) >= 2 and s[0] in '\'"':
# TODO: utf-8 decode s[1:] to be more correct. Probably
# depends on issue #366, a utf-8 library.
d = ord(s[1])
elif len(s) == 0 and typ.endswith('T'):
d = -1
else:
# This works around the fact that in the arg recycling case, you have no spid.
if word_spid == runtime.NO_SPID:
Expand All @@ -252,6 +257,22 @@ def Run(self, cmd_val):
s = '%x' % d
elif typ == 'X':
s = '%X' % d
elif typ.endswith('T'):
# set timezone
tzcell = self.mem.GetCell('TZ')
if tzcell and tzcell.exported and tzcell.val.tag_() == value_e.Str:
tzval = cast(value__Str, tzcell.val)
os.environ['TZ'] = tzval.s
elif 'TZ' in os.environ:
del os.environ['TZ']
time.tzset()

if d == -1: # now
d = None
elif d == -2: # shell start time
d = shell_start_time
s = time.strftime(typ[1:-2], time.localtime(d));

else:
raise AssertionError()

Expand Down
8 changes: 5 additions & 3 deletions spec/builtin-printf.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -541,15 +541,17 @@ status=1
## END

#### %(strftime format)T
# The result depends on timezone
export TZ=Asia/Tokyo
printf '%(%Y-%m-%d)T\n' 1557978599
export TZ=US/Eastern
printf '%(%Y-%m-%d)T\n' 1557978599
echo status=$?
## STDOUT:
2019-05-16
2019-05-15
status=0
## END
## N-I dash/mksh/zsh/ash STDOUT:
status=1
## END
## N-I osh STDOUT:
status=2
## END

0 comments on commit 44d5af8

Please sign in to comment.