[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
일반적인 텍스트로 확장된, 인자를 가지는 매크로는 아마도 충분히 만족스럽지 는 않을 것이다. 여기에 또다른 매크로를 확장하는 여러것들이 있다. 이것들은 실 행시에 결정된다. 예를 들면 일반적으로 조건문이 필요할 것이다. 또한 몇가지의 루프를 만드는 것도 있으면 좋을 것이다. 따라서 여기서는 여러번 어떤 일을 한 다던지, 아니면 주어진 조건이 참인지 검사하는 것들을 소개할 것이다.
5.1 매크로 정의 테스트 | ||
5.2 문자열 비교 | ||
5.4 루프와 재귀 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
m4
에는 두 개의 다른 내장 조건문을 제어하는 것이 있다. 첫번째는
ifdef
이다.
ifdef(name, string-1, opt string-2) |
이것은 매크로가 이미 정의가 되었는지 그렇지 않은지 테스트 하는 것이다.
name이 정의된 매크로의 명칭이라면 ifdef
는
string-1으로 확장되고, 아니면 string-2로 확장된다.
string-2를 생략한다면, 그것은 일반적인 규칙을 따라서 빈 문자열이
된다.
ifdef(`foo', ``foo' is defined', ``foo' is not defined') ⇒foo is not defined define(`foo', `') ⇒ ifdef(`foo', ``foo' is defined', ``foo' is not defined') ⇒foo is defined |
ifdef
매크로는 단지 인자가 있을 때에만 인식된다.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
다른 조건을 제어하는 것은 ifelse
인데, 이것은 훨씬 강력하다.
ifelse
는 긴 주 석을 만든다던지, 또는 일반적인 if-else 와 같이
사용할 수도 있고 여러개로 가 지를 뻗을 수 있다. 이것은 전적으로
제공되는 인자의 개수에 의존한다.
ifelse(comment) ifelse(string-1, string-2, equal, opt not-equal) ifelse(string-1, string-2, equal, ...) |
하나의 인자만으로 ifelse
를 사용한다면, ifelse 는 그 인자를
취소하며, 아무런 출력도 하지 않는다. 이것은 주석을 블록단위로 만들 때
사용하는 m4
의 공통적인 관습이다. dnl
을 사용하면 출력되는
빈공백을 없앨 수 있다. 이런 특별한 사용 법은 GNU m4
가 인식한다.
이 경우에 있어서 인자와 관련된 에러 경고는 결코 트리거되지 않는다.
세 개나 네 개의 인자로 호출한다면 ifelse
는 string-1과
string-2가 같을 경우 (문자대 문자)는 equal로 확장되고 다른
경우는 not-equal로 확장된다.
ifelse(foo, bar, `true') ⇒ ifelse(foo, foo, `true') ⇒true ifelse(foo, bar, `true', `false') ⇒false ifelse(foo, foo, `true', `false') ⇒true |
ifelse
는 네 개보다 더 많은 인자를 가질 수 있다. 네 개보다 많은
인자가 주어 진다면 ifelse
는 case
나 switch
구문과
같은 전통적인 프로그래밍 언어와 같이 작동한다. string-1과
string-2가 같다면 ifelse
는 equal로 확장되고 다른
경우는 첫 세 개의 인자는 건너뛰고 다시 되풀이 한다. 여기에 간단한 예가
있다.
ifelse(foo, bar, `third', gnu, gnats, `sixth', `seventh') ⇒seventh |
보통의 평범한 경우는 위의 예제보다는 좀더 복잡한 양상을 띄게 될 것이다.
ifelse
의 공통된 사용은 다양한 종류의 루프용 매크로 도구로
사용하는 것이다.
ifelse
매크로는 인자가 있을 때에만 인식된다.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
m4
에서 적접적인 루프는 제공하지 않는다. 하지만 매크로는
재귀적으로 될 수 있다. 재귀적 표현의 단계는 제한이 없다. 여러분의
하드웨어나 운영체제에 의해 제한되는 것은 제외하고는...
루프는 재귀적으로 프로그래밍 될 수 있으며 조건문은 앞서와 같이 사용할 수 있다.
shift
라는 내장 매크로가 있는 데 이것은 매크로에서 활성화된
인자들을 되풀 이 하는 데 사용된다.
shift(...) |
괄호안에는 어떠한 개수의 인자도 올수 있으며, 첫 번째 인자를 제외하고는 모 두 확장된다. 확장될 때는 따옴표 처리된 인자 단위로 되고 쉼표로 분리된다.
shift(bar) ⇒ shift(foo, bar, baz) ⇒bar,baz |
다음의 매크로는 shift
의 예인 데, 여기서는 각각의 인자의 순서로
거꾸로 만 들고 있다.
define(`reverse', `ifelse($#, 0, , $#, 1, ``$1'', `reverse(shift($@)), `$1'')') ⇒ reverse ⇒ reverse(foo) ⇒foo reverse(foo, bar, gnats, and gnus) ⇒and gnus, gnats, bar, foo |
별로 흥미있는 예는 아니지만, 위의 것은 shift
와 ifelse
로
간단한 재귀적 루프를 만들 수 있다는 것을 보여준다.
이제 루프 매크로 forloop 을 사용하는 간단한 예제를 보자. 예에서 보는 바와 같이 이것은 간단한 숫자세기를 한다.
forloop(`i', 1, 8, `i ') ⇒1 2 3 4 5 6 7 8 |
인자는 차례대로 반복될 변수명, 처음 가지는 값, 마지막 값, 매회 확장될
텍스 트 이다. 여기에서 매크로 i
는 단지 루프내부에서만 정의된다.
루프가 끝난 후에 는 이전에 가졌던 값을 그대로 유지한다.
For-loop 는 또다시 내장될 수 있다. 다음과 같이
forloop(`i', 1, 4, `forloop(`j', 1, 8, `(i, j) ') ') ⇒(1, 1) (1, 2) (1, 3) (1, 4) (1, 5) (1, 6) (1, 7) (1, 8) ⇒(2, 1) (2, 2) (2, 3) (2, 4) (2, 5) (2, 6) (2, 7) (2, 8) ⇒(3, 1) (3, 2) (3, 3) (3, 4) (3, 5) (3, 6) (3, 7) (3, 8) ⇒(4, 1) (4, 2) (4, 3) (4, 4) (4, 5) (4, 6) (4, 7) (4, 8) ⇒ |
forloop
매크로는 그것자체로 충분히 멋이 있으며 간단한 독립적인
모듈이다. 그리고 처음에 호출하면 먼저 첫 번째 인자의 이전 정의를
저장하고 내부 매크로 _forloop
을 호출한다. 그리고 저장된 첫 번째
인자 정의를 복구한다.
_forloop
매크로는 한 번에 4개의 인자로 확장하며 끝이 났는가를
알아보기 위 해 테스트 한다. 만일 끝이 나지 않았다면 변수의 값을 이미
정의된 매크로인 incr
을 사용하여 하나 증가시키고 다시 재귀적으로
실행된다. (incr
은 see section 증가, 감소 연산자.)
여기에 forloop
를 정의한 유용한 매크로가 있다.
define(`forloop', `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', `$4')popdef(`$1')') define(`_forloop', `$4`'ifelse($1, `$3', , `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')') |
따옴표를 사용할 때 조심하여야 한다. 세 번째 인자만이 따옴표가 없는 데, 각 각은 그것 자체의 이유가 있다. 왜 세 번째 인자가 따옴표가 없는 지를 알려면, 따옴표로 묶었을 때 어떤 일이 일어나는 지를 살펴보면 된다.
이제, 두 개의 유용한 매크로를 살펴보았다. 아마도 그래도 이것으로는 일반적 인 사용에는 뭔가 조금 허전함을 느낄 것이다. 위의 두가지 매크로에서 시작값이 종료값보다 클 경우라던지, 첫 번째 인자가 명칭이 아니라던지 하는 경우의 기본 적인 에러를 처리하는 부분이 조금 미약하다. 이러한 에러를 바로 하는 것은 독 자 여러분의 연습문제로 남겨둔다.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated by Autobuild on October 25, 2015 using texi2html 1.82.