title

Raspberry PI 3

前へ


2020-01-20  「DrRacket PLOT, SICP」
LISPがやりたくなってDrRacketを、

sudo apt install racket

でインストールしたが、

#lang racket
>(require plot)
とやるとDrRacketが途中で消えてしまって動作しない。

そこでソースからビルドすることにした。
Raspberry pi 4Bでやるのが早くていい。
3BだとINSTALLでエラーになるが、何回かmake install するとよい。
make installが長時間かかる。

https://download.racket-lang.org/
Racket
Unix Source
racket-7.5-src.tgz
(https://mirror.racket-lang.org/installers/7.5/racket-7.5-src.tgz)
ダウンロード
$ sudo apt install libffi-dev
  ないかもしれないので一応インストール

$ tar zxvf racket-7.5-src.tgz
$ cd racket-7.5/src
$ mkdir build
$ cd build
$ ../configure --help
$ ../configure --help-racket
 好みのオプションがあるかを見る。

$ ../configure --prefix=/usr/local
 prefixを指定しない場合は解凍したracket-7.5に
 ./bin
  ./share
  ./man 等がmake install した時インストールされる。

$ make
$ sudo make install
$ drracket
[racket.png]

整数が扱いやすい。

#lang sicp
(define (factorial n)
  (if (= n 1)
      1
      (* n (factorial (- n 1)))))

> (factorial 100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

参考:https://sicp.iijlab.net/fulltext/
   計算機プログラムの構造と解釈 第2版
   https://docs.racket-lang.org/sicp-manual/index.html
   SICP Collections

SICPをやる場合の設定。
DrRacketメインメニュー → ファイル → PackegeManager → ダイアログ タグ"Do What I Mean"
Package Source: に”sicp"と入力して、Update ボタンをクリック。
終わったかどうかがわかりにくい。

テスト。
上の定義ウィンドウに、

#lang sicp
入力して、実行ボタンクリック。
下のウィンドウに、

(inc 42)
入力すると、43が帰る。
(#%require sicp-pict)
(paint einstein)
でアインシュタイン画像表示。

上の定義ウィンドウに、

#lang racket 実行ボタンクリック。
下のウィンドウに、
(require sicp-pict)
(paint einstein)
でも同じ。

[racket-sicp-p.png]
2019-12-22  「Raspberry pi 3A+ HDDブート」
Raspberry pi 3B+, 4Bは箱に裸で入っていたのに、静電気防止フィルムの袋に入っていた。
製造するところが違うのかな。

Easpberry Pi 3A+ にUSB HDDを差し込んで、キーボード、マウスなしで使ってみる。
WD Elements SEの1TBポータブルHDDとRSコンポーネンツ5.1V 2.5A ACアダプタを使っても雷マークがでなかった。

最初は、

(1) USBブートできるようにする。(1回やればよい)
・OSイメージをSDカードに書き込む。
・一度OSを立ち上げる。
・OSセットアップはしなくてとよい。

sudo nano /boot/config.txt
---
program_usb_boot_mode=1
---追加
sudo reboot

vcgencmd otp_dump
--
17:3020000a
--確認

次にUSBシリアルケーブルを用意してRASPI-3A+のUARTに接続する。

(2) USB HDDにOSイメージ 2019-09-26-raspbian-buster.img をコピーする。

(3) コピー直後に、VFAT /bootパーティションのconfig.txtファイルに以下を追加。

sudo nano config.txt
---
enable_uart=1
# hdmi_group,hdmi_modeはVNC接続時の画面の大きさ 
hdmi_group=2 
hdmi_mode=85
---追加

sudo nano cmdline.txt
---
plymouth.ignore-serial-consoles
---長い1行の最後にある、これを削除するとブート時のメッセージがシリアルコンソールに表示される

(4) 別PC(Windows,RasPiどちらでも)でUSBシリアル端末を開く。
   115200BPS パリティなし、ハードウェアハンドシェークなし

sudo apt install uc
uc -f -s 115200 -l /dev/ttyUSB0
で通信可能にする。

(5) RasPi 3A+にUSB HDDを、UARTにUSBシリアルケーブルを接続する。
  ディスプレイはあってもなくてもよい。
  ACアダプタを接続する。

(6) しばらくして、USBシリアルケーブル接続された別PCの端末に"login :"が表示されたら、
  最初のOSセットアップが終わってリブートされている。
  ログインユーザ:pi , パスワード:raspberryでログインする。

(7) デスクトップに出るOSインストールのダイアログは出ているが、そちらではできないのでコマンドで手動設定する。

  sudo raspi-config

  ・Piパスワード変更
  ・ホスト名、Wifi設定(Wifi国設定はこのとき)
  ・ロケール、タイムゾーン、キーボード(接続しないのでしなくてもいいい)、Wifi国設定
  ・インターフェース SSH, VNCをONにする。(SerialはすでにON)
  リブートする前に
   固定IPアドレス設定するか、IPアドレスを確認すること。

  sudo reboot

  USBシリアルを外す。

(8) 別PCより、VNC接続する。
  OSインストールのダイアログは出たままなので設定か、キャンセルする。

キーボード、マウスはUSBコネクタは塞がるのでBluetooth接続で使える。
(シリアルコンソールはOS設定のみでの使用なので)
ディスプレイ接続はありなしどちらでもよい。

(9) OSコンパイル
ーーーー
#!/bin/sh
# Usage: sudo ./compile.sh
#
apt install -y  bc bison flex libssl-dev make
cd /usr/src

clone --depth=1 https://github.com/raspberrypi/linux
cd linux

# raspberry pi 1, Zero, Zero W
#KERNEL=kernel 
#make bcmrpi_defconfig

# raspberry pi 2,3,3B+
KERNEL=kernel7
make bcm2709_defconfig

# raspberry pi 4B
#sudo apt-get install bc
#KERNEL=kernel7l
#make bcm2711_defconfig

date >> /usr/src/cmpl-log.txt
make -j4 zImage modules dtbs
date >> /usr/src/cmpl-log.txt
ーーーー
1時間45分
[raspi-3ap.png]
2019-12-20  「Device Driverを作る」
久しぶりにGOPIOキャラクタデバイスドライバを作ってみた。

$ nano gpio00.c
---
#include <stdio.h>
#include <bcm_host.h>

int main(int argc, char* argv[]) {
  printf("0x%08X\n", bcm_host_get_peripheral_address());
  return 0;
}
----
$ cc gpio00.c -I/opt/vc/include -L/opt/vc/lib -lbcm_host -o gpio00
$ ./gpio00
でメモリアドレスを確認する。

参考:「ARMコンピュータ ラズベリー・パイでI/O」第8章 自作LinuxドライバでI/O制御を簡単・確実に! CQ出版
   インタフェース 2002.2月号
     BCM2835-ARM-Peripherals.pdf


$ sudo apt install raspberrypi-kernel-headers

  /usr/src/linux-headers-4.19.75+, ~-4.19.75-V7+, ~4.19.75-V7l+ができる
 uname -r で表示される4.19.75+があること。
 sudo rpi-updateした後ではこれでは作れないので
   sudo apt install --reinstall raspberrypi-bootloader raspberrypi-kernel
   sudo reboot
 で元に戻す。何回もrpi-updateしたら元に戻らないのでカーネルをソースからビルドする。
 Raspberry pi 4BでSSDメモリ上でビルドすると50分くらいだった。(メモリのアクセススピードにより変わる)
 3Bだと倍くらいの時間。
 インストールしてから使う。

$ nano gpio_drv.h
---
/* gpio_drv.h */
#include <linux/ioctl.h>
struct io_info {
        unsigned long   adrs;
        unsigned long   data;
};

#define XXX_MAGIC               '3'
#define XXX_MEM_READ_32		(_IOWR(XXX_MAGIC, 9, int))
#define XXX_MEM_WRITE_32        (_IOWR(XXX_MAGIC, 12, int))

#define BCM2835_PERI_BASE        0x3F000000  /* 4B = 0xFE000000 */
#define GPIO_BASE                (BCM2835_PERI_BASE + 0x200000)
---

$ nano gpiodrv.c
---
#include <linux/init.h>
#include <linux/module.h>
#include <linux/major.h>
#include <linux/kernel.h>	// printk ();

#include <linux/fs.h>		// everything
#include <linux/errno.h>	// error codes
#include <linux/types.h>	// size_t
#include <linux/fcntl.h>	// O_ACCMODE
#include <linux/uaccess.h>	// copy_from/to_user
#include <linux/cdev.h>		// cdev struct.
#include <asm/io.h>
#include "gpio_drv.h"

MODULE_LICENSE ("Dual MIT/GPL");

static int	gpiodrv_init(void);
static void	gpiodrv_exit(void);

int 		gpiodrv_open(struct inode *inode, struct file *filp);
int 		gpiodrv_release(struct inode *inode, struct file *filp);
ssize_t 	gpiodrv_read(struct file *filp, char *buf, size_t count, loff_t *fpos);
ssize_t 	gpiodrv_write(struct file *filp, const char *buf, size_t count, loff_t *fpos);
static long 	gpiodrv_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
int 		gpiodrv_open(struct inode *inode, struct file *filp);

struct file_operations gpiodrv_fops = {
	.owner= THIS_MODULE,
	.read= gpiodrv_read,
	.unlocked_ioctl= gpiodrv_ioctl,
	.write= gpiodrv_write,
	.open= gpiodrv_open,
	.release= gpiodrv_release
};

static dev_t dev_id;
static struct cdev c_dev;
static void *iop;

static int gpiodrv_init(void)
{
	int ret;

  /* ---- initial driver module  --- */
  ret = alloc_chrdev_region( &dev_id,
            0,
            1,
            "gpiodrv"			// Module-name
        );
   if( ret < 0 ){
        printk( KERN_WARNING "[gpiodrv] alloc_chrdev_region failed\n" );
        return ret;
   }
   cdev_init( &c_dev, &gpiodrv_fops );
   c_dev.owner = THIS_MODULE;

   ret = cdev_add( &c_dev, dev_id, 1 );
   if( ret < 0 ){
        printk( KERN_WARNING "[gpiodrv] chrdev add failed\n" );
        return ret;
   }
  /* ---- driver log --- */
   printk( KERN_INFO "[gpiodrv] page_size : %ld, major : %d, minor : %d\n", PAGE_SIZE, MAJOR( dev_id ), MINOR( dev_id ) );
   return(0);
}

static void gpiodrv_exit(void)
{
   cdev_del( &c_dev );

   unregister_chrdev_region( dev_id, 1 );

   printk( KERN_INFO "[gpiodrv] ByeBye gpiodrv Driver!\n");
}

static long gpiodrv_ioctl(struct file *file,
				unsigned int	cmd,
				unsigned long arg) {
   unsigned long io_page;
   unsigned long io_pagesize = PAGE_SIZE;
   struct io_info io;

   printk( KERN_INFO "[gpiodrv] XXX_IO/CONTROL\n");
   switch(cmd) {
	case XXX_MEM_READ_32:
	   get_user(io.adrs,((long*)arg));
	   if( io.adrs > 0x100 ) 	return (-EINVAL);
	   io.adrs &= 0xFFFFFFFC;
	   io_page = GPIO_BASE;

	   iop = ioremap(io_page,PAGE_SIZE);
	   io.data = *((unsigned long*)(iop + io.adrs));
	   iounmap(iop);
	   put_user(io.adrs, (long *)arg);
	   put_user(io.data, ((long *)arg+1));
	   break;
	case XXX_MEM_WRITE_32:
	   get_user(io.adrs,((long*)arg));
	   get_user(io.data,((long*)arg+1));
	   if( io.adrs > 0x100 ) 	return (-EINVAL);
	   io.adrs &= 0xFFFFFFFC;
	   io_page = GPIO_BASE;

	   iop = ioremap(io_page,PAGE_SIZE);
	   *((unsigned long *)(iop + io.adrs)) = io.data;
	   iounmap(iop);
	   put_user(io.adrs, (long *)arg);
	   break;
	default:
	   return(-EINVAL);
   }
   return (0);
}

int gpiodrv_open(struct inode *inode, struct file *filp)
{
   printk( KERN_INFO "[gpiodrv] gpiodrv Open\n");
   return(0);
}

int gpiodrv_release(struct inode *inode, struct file *filp)
{
   printk( KERN_INFO "[gpiodrv] gpiodrv Close\n");
   return(0);
}

ssize_t gpiodrv_read(struct file *filp, char *buf, size_t count, loff_t *fpos)
{
   int i;
   unsigned long   *pd;

   int siz = count > 0x100 ? 0x100 : count;
   siz &= 0xFFFC;
   printk( KERN_INFO "[gpiodrv] gpiodrv Read\n");

   iop = ioremap(GPIO_BASE,PAGE_SIZE);
   pd = (unsigned long *)buf;
   for (i = 0; (i*4) < siz; i++) {
	put_user(*(((unsigned long*)iop) + i), ((long *)buf+i));
   }
   iounmap(iop);

   return(i*4);
}

ssize_t gpiodrv_write(struct file *filp, const char *buf, size_t count, loff_t *fpos)
{
   printk( KERN_INFO "[gpiodrv] write request\n");
   return 0;
}

module_init(gpiodrv_init);
module_exit(gpiodrv_exit);
ーーー
$ nano Makefile
---
obj-m := gpiodrv.o
all:
	make -C /usr/src/linux-headers-$(shell uname -r) M=${PWD} modules
clean:
	make -C /usr/src/linux-headers-$(shell uname -r) M=${PWD} clean
---

ドライバコンパイル
$ make

$ nano install_drv.sh
---
#!/bin/sh
if [ -f gpiodrv.ko ]
then
	DRV=`lsmod|grep gpiodrv`
	if [ "$DRV" != "" ]; then
		/sbin/rmmod gpiodrv
	fi
	/sbin/insmod gpiodrv.ko
	rm -f /dev/gpiodrv0
	major=$(cat /proc/devices|awk "\$2==\"gpiodrv\" {print \$1}")
	mknod /dev/gpiodrv0 c $major 0
	chmod 666 /dev/gpiodrv0
fi
#
# driverファイルはfull pathにして /etc/rc.local 追加
#    if [ -f /yours/path/install_drv.sh ] ; then /yours/path/install_drv.sh ; fi
---
$ chmod +x install_drv.sh

ドライバロード
$ sudo ./install_drv.sh

$ nano led.c
---
/* led.c           */
/* cc led.c -o led */
/* ./led           */
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <time.h>
#include "gpio_drv.h"
unsigned char b[4096];

void dump4(unsigned long *p, int b)
{
  int n, o;

  for(n = 0; (n*4) < b; n++ ) {
    o = (n*4) & 0x0f;
    if( n>0 && o == 0) {
	printf("\n");
    }
    if( o == 0) {
	printf("%08X: ", GPIO_BASE+(n*4));
    }
    printf("%08X ", *p++);
  }
  printf("\n");
}

int main()
{
int fd;
long n, r;
struct io_info ioc;

	printf( "**start\n");
  	if (( fd = open("/dev/gpiodrv0", O_RDWR)) < 0 ){
		printf( "Error device?\n");
		return -1;
	}
	printf( "--Memory Dump\n");
	ioc.adrs = 0x00000000;
	ioc.data = 0xFFFFFFFF;
	for( n = 0; n < 16; n++ ) {
		r = ioctl(fd, XXX_MEM_READ_32, &ioc);
		printf("Mem: 0x%08X = 0x%08X\n",GPIO_BASE+ioc.adrs, ioc.data);
		ioc.adrs += 4;
	}


	printf( "--LED Blink\n");
	ioc.adrs = 0x00000004;
	ioc.data = 0xFFFFFFFF;
	r = ioctl(fd, XXX_MEM_READ_32, &ioc);	// read GPFSEL1
	ioc.data &= 0xFFFFF1FF;
	ioc.data |= 0x00000200;			// Output GPIO13
	r = ioctl(fd, XXX_MEM_WRITE_32, &ioc);	// write GPFSEL1
	ioc.adrs = 0x00000028;
	ioc.data = 0x00002000;			// set LOW GPIO13 pin
	r = ioctl(fd, XXX_MEM_WRITE_32, &ioc);	// write GPCLR0
        ioc.data = 0x00002000;
	for( n = 0; n < 10; n++ ) {
		sleep(1);
		if ( !(n & 1) )
			ioc.adrs = 0x0000001C;		// set HIGH GPIO13 pin
		else
			ioc.adrs = 0x00000028;		// set LOW GPIO13 pin
		r = ioctl(fd, XXX_MEM_WRITE_32, &ioc);	// write GPSET0
                printf("count: %d / 10 \n", n);
	}
	ioc.adrs = 0x00000028;
	ioc.data = 0x00002000;				// set LOW GPIO13 pin
	r = ioctl(fd, XXX_MEM_WRITE_32, &ioc);		// write GPCLR0

	printf( "--MEMORY READ\n");
	read(fd, b, 256);
	dump4((unsigned long*)b, 256);
	close(fd);
	printf( "** end\n");
	return 0;
}
---
$ cc led.c -o led

LEDをGPIO-13に配線しておくこと。

 GPIO13 <---/\/\/\---▷|---> GND
             1kΩ

$ ./led
...
**start
--Memory Dump
Mem: 0x3F200000 = 0x00000000
Mem: 0x3F200004 = 0x00000240
Mem: 0x3F200008 = 0x08000000
Mem: 0x3F20000C = 0x3FFFFFFF
Mem: 0x3F200010 = 0x24200824
Mem: 0x3F200014 = 0x00000924
Mem: 0x3F200018 = 0x00000000
Mem: 0x3F20001C = 0x6770696F
Mem: 0x3F200020 = 0x6770696F
Mem: 0x3F200024 = 0x6770696F
Mem: 0x3F200028 = 0x6770696F
Mem: 0x3F20002C = 0x6770696F
Mem: 0x3F200030 = 0x6770696F
Mem: 0x3F200034 = 0x100081FF
Mem: 0x3F200038 = 0x003EF3FF
Mem: 0x3F20003C = 0x00000000
--LED Blink
count: 0 / 10 
count: 1 / 10 
count: 2 / 10 
count: 3 / 10 
count: 4 / 10 
count: 5 / 10 
count: 6 / 10 
count: 7 / 10 
count: 8 / 10 
count: 9 / 10 
--MEMORY READ
3F200000: 00000000 00000240 08000000 3FFFFFFF 
3F200010: 24200824 00000924 00000000 6770696F 
3F200020: 6770696F 6770696F 6770696F 6770696F 
3F200030: 6770696F 100081FF 003EF3FB 00000000 
3F200040: 00000000 00000000 00000000 00000000 
3F200050: 00000000 00000000 00000000 00000000 
3F200060: 00000000 00000000 00000000 00000000 
3F200070: 00000000 00000000 00000000 00000000 
3F200080: 00000000 00000000 00000000 00000000 
3F200090: 00000000 00000002 00000000 00000000 
3F2000A0: 00000000 FFFFFFFF 003FFFFF 6770696F 
3F2000B0: 00000000 6770696F 6770696F 6770696F 
3F2000C0: 00000000 00000000 00000000 00000000 
3F2000D0: 6770696F 6770696F 6770696F 6770696F 
3F2000E0: 6770696F 6770696F 6770696F 6770696F 
3F2000F0: 6770696F 6770696F 6770696F 6770696F 
** end
...

2019-11-15  「GNUCOBOL 3.0 インストール」
久しぶりにCOBOLプログラムをやってみました。
OPEN COBOLがGNU COBOLになっていた。
OPEN COBOLもまだ健在でUPDATEされている。同じではないです。
GNUCOBOLはC言語インターフェースがだいぶ修正されている。

Raspberry piにはパッケージでインストールできるのだがcobcrunの機能が新しいのと違うのでソースからインストール。

(1)download
https://jaist.dl.sourceforge.net/project/open-cobol/gnu-cobol/3.0/gnucobol-3.0-rc1.tar.xz
または

https://ja.osdn.net/projects/sfnet_open-cobol/
gnucobol-3.0_nightly_r2793.tar.gz

(2)参考:
https://open-cobol.sourceforge.io/faq/GnuCOBOLFAQ.pdf
GnuCOBOL FAQ Release 2.4.392  sep 28, 2019

https://open-cobol.sourceforge.io/
GnuCOBOL 3.1 (dev) Programmers Guide (A4).pdf
GnuCOBOL FAQ (PDF)

https://sourceforge.net/p/open-cobol/discussion/cobol/thread/94a361d1/9a38/12fa/af3c/fefd/0ae2/7e53/attachment/GnuCOBOL_C%20data_routines.pdf
GnuCOBOL – API for C access to COBOL data(PDF)

(3)インストール手順
gnucobol-3.0-rc1.tar.xz 解凍
cd gnucobol-3.0-rc1

sudo apt install libdb-dev libgmp-dev bison flex help2man texinfo libxml2-dev libncursesw5-dev

他に、Autoconf、Automake、 Libtool、 m4、Gettext もあるかどうかをチェック

./configure
make
make check
sudo make install
nano hello.cob
---hello.cob-----------作成-----------------------------------------------------
123456*7A901B345678901234567890123456789012345678901234567890123456789012M4567890
      * Sample COBOL program
        IDENTIFICATION DIVISION.
        PROGRAM-ID. hello.
        PROCEDURE DIVISION.
          DISPLAY "Hello, world!".
          STOP RUN.
-----------
cobc -x hello.cob
./hello
Hello, world!

翻訳・実行でエラーがないこと。

licob.so ロードエラーの時は、

sudo nano /etc/ld.so.conf
---
/usr/local/lib
を追加するか、/etc/ld.so.conf.d/の下に
上記の内容で”適当な名前xxx.conf”ファイルを作る。

sudo ldconfig

(4)SCREEN SECTIONの日本語対応
ncursesを使っているので通常のCでの対処と同じ。

gnu-cobol 解凍ディレクトリの中にある。
(日本語入力・修正は、コマンドライン入力のようにはなっていないからコメントなのかも)
----lobcob/screenio.c----- 410行付近

#if	1	/* RXWRXW - setlocale */ <<<=== 0 を 1 にする
#ifdef	HAVE_SETLOCALE
	if (cobglobptr->cob_locale_orig) {
		setlocale (LC_ALL, cobglobptr->cob_locale_orig);
	}
コメント3行///if (cobglobptr->cob_locale_ctype) {
	 ///	setlocale (LC_CTYPE, cobglobptr->cob_locale_ctype);
	 ///}
#endif
#endif

	if (!initscr ()) {
		cob_runtime_error (_("failed to initialize curses"));
		/* FIXME: likely should raise an exception instead */
		cob_stop_run (1);
	}
	cobglobptr->cob_screen_initialized = 1;
#ifdef	HAVE_USE_LEGACY_CODING
	use_legacy_coding (2);
#endif

#if	0	/* RXWRXW - setlocale */
#ifdef	HAVE_SETLOCALE
	if (cobglobptr->cob_locale) {
		setlocale (LC_ALL, cobglobptr->cob_locale);
		setlocale (LC_CTYPE, "C");
	}
#endif
#endif

	cbreak ();
	keypad (stdscr, 1);
ーーーーー
か、または、コンパイラソースを修正しない場合は、
--- locale.c ---作成
#include <locale.h>
void LOCALE(void)
{
	setlocale(LC_ALL,"");
}
-------------
COBOL ソースのSCREEN SECTIONへのアクセス前に
  CALL "LOCALE".
といれて、
cobc -x COBOLソース locale.c
でリンクして使う。

(5)SCREEN SECTION のプログラム
COBOLプログラム
---crtform.cob-----------作成-----------------------------------------------------
123456*7A901B345678901234567890123456789012345678901234567890123456789012M4567890
      * ******************************
      * compile: cobc -x crtform.cob
      * ******************************
       identification division.
       program-id. crtform.
       environment division.
       configuration section.
       special-names.
         crt status is yesno.
       data division.
       working-storage section.
      *     screenio は crt status の定義 
       copy screenio.
       01 in-data pic X(30).
       01 msg     pic x(40).
       01 yesno   pic 9999.
       screen section.
       01 one-screen.
          03 line 3 column 20 value "タイトル".
          03 line 5 column 16 value "入力:".
       01 two-screen.
          03 line 5 column 23 using in-data.
      *...................
       procedure division.
      *  CALL "LOCALE".
         move 9999 to yesno.
         perform until yesno = COB-SCR-OK
            move "入力してね!" to msg
            display msg at line 10 col 5
            display one-screen two-screen
            accept two-screen
            display two-screen
            move "いいですか?(Y=Enter/N=BackSpace)" to msg
            display msg at line 10 col 5
            accept omitted
         end-perform.
         goback.
         end program crtform.
-------
cobc -x crtform
./crtfotm

実行表示
ーーーーーーー

                   タイトル

               入力: 漢字入力abc_input_____________




    いいですか?(Y=Enter/N=BackSpace) 


ーーーーーーー
カラム位置は漢字を2、半角英数字を1として数える。
入出力領域はUTF-8文字のバイト数で数える。漢字の後は間があいてしまう。
入力時の修正は良くない。先頭から入れ直す。

表紙

次へ