aboutsummaryrefslogtreecommitdiff
path: root/zh_TW.UTF-8/books/developers-handbook/tools/chapter.xml
blob: c9ca702ca202f0025d683ad46aec30f70ca9aaf8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
<?xml version="1.0" encoding="utf-8"?>
<!--
     The FreeBSD Documentation Project

     $FreeBSD$
     Original revision: 1.46
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="tools">
  <info><title>程式開發工具</title>
    <authorgroup>
      <author><personname><firstname>James</firstname><surname>Raynard</surname></personname><contrib>Contributed by </contrib></author>
      <author><personname><firstname>Murray</firstname><surname>Stokely</surname></personname></author>
    </authorgroup>
  </info>

  
  <sect1 xml:id="tools-synopsis"><title>概敘</title>

    <para>本章將介紹如何使用一些 FreeBSD 所提供的程式開發工具(programing tools),
      本章所介紹的工具程式在其他版本的 &unix; 上也可使用,
      在此 <emphasis>並不會</emphasis> 嘗試描述寫程式時的每個細節,
      本章大部分篇幅都是假設你以前沒有或只有少數的寫程式經驗,
      不過,還是希望大多數的程式開發人員都能從中重新得到一些啟發。</para>

  </sect1>

  <sect1 xml:id="tools-intro"><title>簡介</title>

    <para>FreeBSD 提供一個非常棒的開發環境,
      比如說像是 C、C++、Fortran 和 assembler(組合語言)的編譯器(compiler),
      在 FreeBSD 中都已經包含在基本的系統中了
      更別提 Perl 和其他標準 &unix; 工具,像是<command>sed</command> 以及 <command>awk</command>,
      如果你還是覺得不夠,FreeBSD在 Ports collection 中還提供其他的編譯器和直譯器(interpreter),
      FreeBSD 相容許多標準,像是 <acronym>&posix;</acronym><acronym>ANSI</acronym> C,
      當然還有它所繼承的 BSD 傳統。
      所以在 FreeBSD 上寫的程式不需修改或頂多稍微修改,就可以在許多平台上編譯、執行。</para>

    <para>無論如何,就算你從來沒在 &unix; 平台上寫過程式,也可以徹底感受到FreeBSD 令人無法抗拒的迷人魔力。
      本章的目標就是協助你快速上手,而暫時不需深入太多進階主題,
      並且講解一些基礎概念,以讓你可以瞭解我們在講些什麼。</para>

    <para>本章內容並不要求你得有程式開發經驗,或者你只有一點點的經驗而已。
      不過,我們假設你已經會 &unix; 系統的基本操作,
      而且更重要的是,請保持樂於學習的心態!</para>

  </sect1>

  <sect1 xml:id="tools-programming">
    <title>Programming 概念</title>

    <para>簡單的說,程式只是一堆指令的集合體;而這些指令是用來告訴電腦應該要作那些事情。
      有時候,指令的執行取決於前一個指令的結果而定。
      本章將會告訴你有 2 個主要的方法,讓你可以對電腦下達這些指示(instruction) 或 <quote>命令(commands)</quote>。
      第一個方法就是 <firstterm>直譯器(interpreter)</firstterm>,
      而第二個方法是 <firstterm>編譯器(compiler)</firstterm>。
      由於對於電腦而言,人類語言的語意過於模糊而太難理解,
      因此命令(commands)就常會以一種(或多種)程式語言寫成,用來指示電腦所要執行的特定動作為何。</para>

    <sect2>
      <title>直譯器</title>

      <para>使用直譯器時,所使用的程式語言就像變成一個會和你互動的環境。
        當在命令提示列上打上命令時,直譯器會即時執行該命令。
        在比較複雜的程式中,可以把所有想下達的命令統統輸入到某檔案裡面去,
        然後呼叫直譯器去讀取該檔案,並且執行你寫在這個檔案中的指令。
        如果所下的指令有錯誤產生,大多數的直譯器會進入偵錯模式(debugger),
        並且顯示相關錯誤訊息,以便對程式除錯。</para>

      <para>這種方式好處在於:可以立刻看到指令的執行結果,以及錯誤也可迅速修正。
	    相對的,最大的壞處便是當你想把你寫的程式分享給其他人時,這些人必須要有跟你一樣的直譯器。
	    而且別忘了,他們也要會使用直譯器直譯程式才行。
	    當然使用者也不希望不小心按錯鍵,就進入偵錯模式而不知所措。
	    就執行效率而言,直譯器會使用到很多的記憶體,
	    而且這類直譯式程式,通常並不會比編譯器所編譯的程式的更有效率。</para>

      <para>筆者個人認為,如果你之前沒有學過任何程式語言,最好先學學習直譯式語言(interpreted languages),
	    像是 Lisp,Smalltalk,Perl 和 Basic 都是,&unix; 的 shell 像是 <command>sh</command><command>csh</command>
	    它們本身就是直譯器,事實上,很多人都在它們自己機器上撰寫各式的 shell <quote>script</quote>,
	    來順利完成各項 <quote>housekeeping(維護)</quote> 任務。
	    &unix; 的使用哲學之一就是提供大量的小工具,
	    並使用 shell script 來組合運用這些小工具,以便工作更有效率。</para>
    </sect2>

    <sect2>
      <title>FreeBSD 提供的直譯器</title>

      <para>下面這邊有份 &os; Ports Collection 所提供的直譯器清單,還有討論一些比較受歡迎的直譯式語言</para>

      <para>至於如何使用 Ports Collection 安裝的說明,可參閱 FreeBSD Handbook 中的
        <link xlink:href="&url.books.handbook;/ports-using.html">Ports章節</link></para>
      <variablelist>
	<varlistentry>
	  <term><acronym>BASIC</acronym></term>

	  <listitem>
	    <para>BASIC 是 Beginner's ALL-purpose Symbolic Instruction Code 的縮寫。
	      BASIC 於 1950 年代開始發展,最初開發這套語言的目的是為了教導當時的大學學生如何寫程式。
	      到了 1980<acronym>BASIC</acronym>已經是很多 programmer 第一個學習的程式語言了。
	      此外,BASIC 也是 Visual Basic 的基礎。</para>

	    <para>FreeBSD Ports Collection 也有收錄相關的 BASIC 直譯器。
	      Bywater Basic 直譯器放在 <package>lang/bwbasic</package>。
	      而 Phil Cockroft's Basic 直譯器(早期也叫 Rabbit Basic)放在 <package>lang/pbasic</package></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Lisp</term>

	  <listitem>
	    <para>LISP 是在 1950 年代開始發展的一個直譯式語言,而且 LISP 就是一種
	      <quote>number-crunching</quote> languages(迅速進行大量運算的程式語言),在當時算是一個普遍的程式語言。
	      LISP 的表達不是基於數字(numbers),而是基於表(lists)。
	      而最能表示出 LISP 特色的地方就在於: LISP 是 <quote>List Processing</quote> 的縮寫。
	      在<acronym>人工智慧(Artificial Intelligence, AI)</acronym>領域上 LISP 的各式應用非常普遍。</para>

	    <para>LISP 是非常強悍且複雜的程式語言,但是缺點是程式碼會非常大而且難以操作。</para>

	    <para>絕大部分的 LISP 直譯器都可以在 &unix; 系統上運作,當然 &os; 的 Ports Collection 也有收錄。
	      GNU Common Lisp 收錄在 <package>lang/gcl</package>,
	      Bruno Haible 和 Michael Stoll 的 CLISP 收錄在 <package>lang/clisp</package>
	      ,此外 CMUCL(包含一個已經最佳化的編譯器),
	      以及其他簡化版的 LISP 直譯器(比如以 C 語言寫的 SLisp,只用幾百行程式碼就實作大多數 Common Lisp 的功能)
	      則是分別收錄在 <package>lang/cmucl</package> 以及
	      <package>lang/slisp</package></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Perl</term>

	  <listitem>
	    <para>對系統管理者而言,最愛用 perl 來撰寫 scripts 以管理主機,
	      同時也經常用來寫 WWW 主機上的 <acronym>CGI</acronym> Script 程式。</para>

	    <para>Perl 在 Ports Collection 內的 <package>lang/perl5</package>。
	      而 &os; 4.X 則是把 Perl 裝在 <command>/usr/bin/perl</command></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Scheme</term>

	  <listitem>
	    <para>Scheme 是 LISP 的另一分支,Scheme 的特點就是比 Common LISP 還要簡潔有力。
	      由於 Scheme 簡單,所以很多大學拿來當作第一堂程式語言教學教材。
	      而且對於研究人員來說也可以快速的開發他們所需要的程式。</para>

	    <para>Scheme 收錄在 <package>lang/elk</package>,
	      Elk Scheme 直譯器(由麻省理工學院所發展的 Scheme 直譯器)收錄在
	      <package>lang/mit-scheme</package>,
	      SCM Scheme Interpreter 收錄在 <package>lang/scm</package></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Icon</term>

	  <listitem>
	    <para>Icon 屬高階程式語言,Icon 具有強大的字串(String)和結構(Structure)處理能力。
	      &os; Ports Collection 所收錄的 Icon 直譯器版本則是放在
	      <package>lang/icon</package></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Logo</term>

	  <listitem>
	    <para>Logo 是種容易學習的程式語言,最常在一些教學課程中被拿來當作開頭範例。
	      如果要給小朋友開始上程式語言課的話,Logo 是相當不錯的選擇。
	      因為,即使對小朋友來說,要用 Logo 來秀出複雜多邊形圖形是相當輕鬆容易的。</para>

	    <para>Logo 在 &os; Ports Collection 的最新版則是放在 <package>lang/logo</package></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Python</term>

	  <listitem>
	    <para>Python 是物件導向的直譯式語言,
	      Python 的擁護者總是宣稱 Python 是最好入門的程式語言。
	      雖然 Python 可以很簡單的開始,但是不代表它就會輸給其他直譯式語言(像是 Perl 和 Tcl),
	      事實證明 Python 也可以拿來開發大型、複雜的應用程式。</para>

	    <para>&os; Ports Collection 收錄在 <package>lang/python</package></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Ruby</term>

	  <listitem>
	    <para>Ruby 是純物件導向的直譯式語言。
	      Ruby 目前非常流行,原因在於他易懂的程式語法結構,在撰寫程式時的彈性,
	      以及天生具有輕易的發展維護大型專案的能力。</para>

	    <para>&os; Ports Collection 收錄在 <package>lang/ruby8</package></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Tcl and Tk</term>

	  <listitem>
	    <para>Tcl 是內嵌式的直譯式語言,讓 Tcl 可以如此廣泛運用的原因是 Tcl 的移植性。
	      Tcl 也可以快速發展一個簡單但是具有雛型的程式或者具有完整功能的程式。</para>

	    <para>Tcl 許多的版本都可在 &os; 上運作,而最新的 Tcl 版本為 Tcl 8.4&os; Ports Collection 收錄在 <package>lang/tcl84</package></para>
	  </listitem>
	</varlistentry>
      </variablelist>
    </sect2>

    <sect2>
      <title>編譯器</title>

      <para>編譯器和直譯器兩者相比的話,有些不同,首先就是必須先把程式碼統統寫入到檔案裡面,
        然後必須執行編譯器來試著編譯程式,如果編譯器不接受所寫的程式,那就必須一直修改程式,
        直到編譯器接受且把你的程式編譯成執行檔。
        此外,也可以在提示命令列,或在除錯器中執行你編譯好的程式看看它是否可以運作。
	<footnote>
	  <para>如果在提示命令列下執行,那麼有可能會產生 core dump。</para>
	</footnote></para>

      <para>很明顯的,使用編譯器並不像直譯器般可以馬上得到結果。
        不管如何,編譯器允許你作很多直譯器不可能或者是很難達到的事情。
        例如:撰寫和作業系統密切互動的程式,甚至是你自己寫的作業系統!
        當你想要寫出高效率的程式時,編譯器便派上用場了。
        編譯器可以在編譯時順便最佳化你的程式,但是直譯器卻不行。
        而編譯器與直譯器最大的差別在於:當你想把你寫好的程式拿到另外一台機器上跑時,
        你只要將編譯器編譯出來的可執行檔,拿到新機器上便可以執行,
        而直譯器則必須要求新機器上,必須要有跟另一台機器上相同的直譯器,
        才能組譯執行你的程式!</para>

      <para>編譯式的程式語言包含 Pascal、C 和 C++,
        C 和 C++ 不是一個親和力十足的語言,但是很適合具有經驗的 Programmer。
        Pascal 其實是一個設計用來教學用的程式語言,而且也很適合用來入門,
        &os; 預設並沒有把 Pascal 整合進 base system 中,
        但是 GNU Pascal Compiler 和 Free Pascal Compiler 都可分別在
        <package>lang/gpc</package><package>lang/fpc</package> 中找到。</para>

      <para>如果你用不同的程式來寫編譯式程式,那麼不斷地編輯-編譯-執行-除錯的這個循環肯定會很煩人,
        為了更簡化、方便程式開發流程,很多商業編譯器廠商開始發展所謂的 <acronym>IDE</acronym>
        (Integrated Development Environments) 開發環境,
        FreeBSD 預設並沒有把 IDE 整合進 base system 中,
        但是你可透過 <package>devel/kdevelop</package> 安裝 kdevelop
        或使用 <application>Emacs</application> 來體驗 IDE 開發環境。
        在後面的 <xref linkend="emacs"/> 專題將介紹,如何以 <application>Emacs</application> 來作為 IDE 開發環境。</para>
    </sect2>


  </sect1>


  <sect1 xml:id="tools-compiling">
    <title><command>cc</command> 來編譯程式</title>

      <para>本章範例只有針對 GNU C compiler 和 GNU C++ compiler 作說明,
        這兩個在 FreeBSD base system 中就有了,
        直接打 <command>cc</command><command>gcc</command> 就可以執行。
        至於,如何用直譯器產生程式的說明,通常可在直譯器的文件或線上文件找到說明,因此不再贅述。</para>

      <para>當你寫完你的傑作後,接下來便是讓這個程式可以在 FreeBSD 上執行,
        通常這些要一些步驟才能完成,有些步驟則需要不同程式來完成。</para>

    <procedure>
      <step>
        <para>預先處理(Pre-process)你的程式碼,移除程式內的註解,和其他技巧,
          像是 expanding(擴大) C 的 marco。</para>
      </step>

      <step>
        <para>確認你的程式語法是否確實遵照 C/C++ 的規定,如果沒有符合的話,編譯器會出現警告。</para>
      </step>

      <step>
        <para>將原始碼轉成組合語言 &mdash; 它跟機器語言(machine code)非常相近,但仍在人類可理解的範圍內(據說應該是這樣)。
	  <footnote>
        <para>嚴格說起來,在這個階段 <command>cc</command> 並不是真的把原始程式轉成組合語言,
          而是轉為 machine-independent 的 <firstterm>p-code</firstterm></para>
	  </footnote></para>
      </step>

      <step>
        <para>把組合語言轉成機器語言 &mdash; 是的,這裡說的機器語言就是常提到的 bit 和 byte,也就是 10</para>
      </step>

      <step>
        <para>確認程式中用到的函式呼叫、全域變數是否正確,舉例來說:如若呼叫了不存在的函式,編譯器會顯示警告。</para>
      </step>

      <step>
        <para>如果程式是由程式碼檔案來編譯,編譯器會整合起來。</para>
      </step>

      <step>
        <para>編譯器會負責產生東西,讓系統上的 run-time loader 可以把程式載入記憶體內執行。</para>
      </step>

      <step>
        <para>最後會把編譯完的執行檔存在硬碟上。</para>
      </step>
    </procedure>

    <para>通常 <firstterm>編譯(compiling)</firstterm> 是指第 1 到第 4 個步驟。
      &mdash; 其他步驟則稱為 <firstterm>連結(linking)</firstterm>,
      有時候步驟 1 也可以是指 <firstterm>預先處理(pre-processing)</firstterm>,
      而步驟 3 到步驟 4 則是 <firstterm>組譯(assembling)</firstterm></para>

    <para>幸運的是,你可以不用理會以上細節,編譯器都會自動完成。
      因為 <command>cc</command> 只是是個前端程式(front end),它會依照正確的參數來呼叫相關程式幫你處理。
      只需打:</para>
    <screen>&prompt.user; <userinput>cc foobar.c</userinput></screen>

    <para>上述指令會把 <filename>foobar.c</filename> 開始編譯,並完成上述動作。
      如果你有許多檔案需要編譯,那請打類似下列指令即可:</para>

    <screen>&prompt.user; <userinput>cc foo.c bar.c</userinput></screen>

    <para>記住語法錯誤檢查就是 &mdash; 純粹檢查語法錯誤與否,
      而不會幫你檢測任何邏輯錯誤,比如:無限迴圈,或是排序方式想用 binary sort 卻弄成 bubble sort。
      <footnote>
        <para>剛所說的 binary sort 和 bubble sort 問題,
          在已排序好的序列中,binary sort 搜索效率會比 bubble sort 好。</para>
      </footnote></para>

    <para><command>cc</command> 有非常多的選項,都可透過線上手冊來查。
      下面只提一些必要且重要的選項,以作為例子。</para>

    <variablelist>
      <varlistentry>
	<term><option>-o <replaceable>檔名</replaceable></option></term>

	<listitem>
	  <para><option>-o</option> 編譯後的執行檔檔名,如果沒有使用這選項的話,
	    編譯好的程式預設檔名將會是 <filename>a.out</filename>

	    <footnote>
	      <para>至於 <option>-o</option> 的原因,則是一團歷史迷霧了。</para>
	    </footnote></para>

	  <informalexample>
	    <screen>&prompt.user; <userinput>cc foobar.c</userinput>               <lineannotation>執行檔就是 a.out</lineannotation>
&prompt.user; <userinput>cc -o foobar foobar.c</userinput>     <lineannotation>執行檔就是 foobar</lineannotation>
	    </screen>
	  </informalexample>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-c</option></term>

	<listitem>
	  <para>使用 <option>-c</option> 時,只會編譯原始碼,而不作連結(linking)。
	    當只想確認語法是否正確或使用 Makefile 來編譯程式時,這個選項非常有用。</para>

	  <informalexample>
	    <screen>
        &prompt.user; <userinput>cc -c foobar.c</userinput>
	    </screen>
	  </informalexample>

	  <para>這會產生叫做 <filename>foobar</filename><firstterm>object file</firstterm>(非執行檔)。
	    這檔可以與其他的 object file 連結在一起,而成執行檔。</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-g</option></term>

	<listitem>
	  <para><option>-g</option> 將會把一些給 gdb 用的除錯訊息包進去執行檔裡面,所謂的除錯訊息例如:
	    程式在第幾行出錯、那個程式第幾行做什麼函式呼叫等等。除錯資訊<emphasis>非常</emphasis>好用。
	    但缺點就是:對於程式來說,額外的除錯訊息會讓編譯出來的程式比較肥些。
	    <option>-g</option> 的適用時機在於:當程式還在開發時使用就好,
	    而當你要釋出你的 <quote>發行版本(release version)</quote>
	    或者確認程式可運作正常的話,就不必用 <option>-g</option> 這選項了。</para>

	  <informalexample>
	    <screen>&prompt.user; <userinput>cc -g foobar.c</userinput>
	    </screen>
	  </informalexample>

	  <para>這動作會產生有含除錯訊息的執行檔。
	    <footnote>
	      <para>請注意,因為上例沒用 <option>-o</option> 以指定執行檔名稱,
	        所以執行檔會是 <filename>a.out</filename> 這檔。
	        那麼,要如何產生 <filename>foobar</filename> 的執行檔並內含除錯訊息,
	        這就留待看倌們練習一下囉。</para>
	    </footnote></para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-O</option></term>

	<listitem>
	  <para><option>-O</option> 會產生最佳化的執行檔,
	    編譯器會使用一些技巧,來讓程式可以跑的比未經最佳化的程式還快,
	    可以在大寫 O 後面加上數字來指明想要的最佳化層級。
	    但是最佳化還是會有一些錯誤,舉例來說在 FreeBSD 2.10 release 中用 <command>cc</command>
	    且指定 <option>-O2</option> 時,在某些情形下會產生錯誤的執行檔。</para>

	  <para>只有當要釋出發行版本、或者加速程式時,才需要使用最佳化選項。</para>

	  <informalexample>
	    <screen>&prompt.user; <userinput>cc -O -o foobar foobar.c</userinput>
	    </screen>
	  </informalexample>

	  <para>這會產生 <filename>foobar</filename> 執行檔的最佳化版本。</para>
	</listitem>
      </varlistentry>
    </variablelist>

    <para>以下三個參數將會強迫 <command>cc</command> 確認程式碼是否符合一些國際標準的規範,
      也就是通常說的 <acronym>ANSI</acronym> 標準,
      而 <acronym>ANSI</acronym> 嚴格來講屬 <acronym>ISO</acronym> 標準。</para>

    <variablelist>
      <varlistentry>
	<term><option>-Wall</option></term>

	<listitem>
	  <para><option>-Wall</option> 顯示 <command>cc</command>  維護者所認為值得注意的所有警告訊息。
	    不過這名字可能會造成誤解,事實上它並未完全顯示 <command>cc</command> 所能注意到的各項警告訊息。</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-ansi</option></term>

	<listitem>
	  <para><option>-ansi</option> 關閉 <command>cc</command> 特有的某些特殊非 ANSI C 標準功能。
	    不過這名字可能會造成誤解,事實上它並不保證你的程式會完全符合 ANSI 標準。</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-pedantic</option></term>

	<listitem>
	  <para>全面關閉 <command>cc</command> 所特有的非 <acronym>ANSI</acronym>  C 標準功能。</para>
	</listitem>
      </varlistentry>
    </variablelist>

    <para>除了這些參數,<command>cc</command> 還允許你使用一些額外的參數取代標準參數,有些額外參數非常有用,
      但是實際上並不是所有的編譯器都有提供這些參數。
      照標準來寫程式的最主要目的就是,希望你寫出來的程式可以在所有編譯器上編譯、執行無誤,
      當程式可以達成上述目的時,就稱為 <firstterm>portable code(移植性良好的程式碼)</firstterm></para>

    <para>一般來說,在撰寫程式時就應要注意『移植性』。
      否則。當想把程式拿到另外一台機器上跑的時候,就可能得需要重寫程式。</para>

    <informalexample>
      <screen>&prompt.user; <userinput>cc -Wall -ansi -pedantic -o foobar foobar.c</userinput></screen>
    </informalexample>

    <para>上述指令會確認 <filename>foobar.c</filename> 內的語法是否符合標準,
      並且產生名為 <filename>foobar</filename> 的執行檔。</para>

    <variablelist>
      <varlistentry>
	<term><option>-l<replaceable>library</replaceable></option></term>

	<listitem>
	  <para>告訴 gcc 在連結(linking)程式時你需要用到的函式庫名稱。</para>

	  <para>最常見的情況就是,當你在程式中使用了 C 數學函式庫,
	    跟其他作業平台不一樣的是,這函示學函式都不在標準函式庫(library)中,
	    因此編譯器並不知道這函式庫名稱,你必須告訴編譯器要加上它才行。</para>

	  <para>規則很簡單,如果有個函式庫叫做 <filename>libsomething.a</filename>,
	    就必須在編譯時加上參數 <option>-l<replaceable>something</replaceable></option> 才行。
	    舉例來說,數學函式庫叫做 <filename>libm.a</filename>,
	    所以你必須給 <command>cc</command> 的參數就是 <option>-lm</option>。
	    一般情況下,通常會把這參數必須放在指令的最後。</para>

	  <informalexample>
	    <screen>&prompt.user; <userinput>cc -o foobar foobar.c -lm</userinput>
	    </screen>
	  </informalexample>

	  <para>上面這指令會讓 gcc 跟數學函式庫作連結,以便你的程式可以呼叫函式庫內含的數學函式。</para>

	  <para>如果你正在編譯的程式是 C++ 程式碼,你還必須額外指定 <option>-lg++</option> 或者是
	    <option>-lstdc++</option>。
	    如果你的 FreeBSD 是 2.2(含)以後版本,
	    你可以用指令 <command>c++</command> 來取代 <command>cc</command>。
	    在 FreeBSD 上 <command>c++</command> 也可以用 <command>g++</command> 取代。</para>

	  <informalexample>
	    <screen>&prompt.user; <userinput>cc -o foobar foobar.cc -lg++</userinput>     <lineannotation>適用 FreeBSD 2.1.6 或更早期的版本</lineannotation>
&prompt.user; <userinput>cc -o foobar foobar.cc -lstdc++</userinput>  <lineannotation>適用 FreeBSD 2.2 及之後的版本</lineannotation>
&prompt.user; <userinput>c++ -o foobar foobar.cc</userinput>
	    </screen>
	  </informalexample>

	  <para>上述指令都會從原始檔 <filename>foobar.cc</filename> 編譯產生名為 <filename>fooboar</filename> 的執行檔。
	    這邊要提醒的是在 &unix; 系統中 C++ 程式傳統都以 <filename>.C</filename><filename>.cxx</filename> 或者是 <filename>.cc</filename> 作為副檔名,
	    而非 &ms-dos; 那種以 <filename>.cpp</filename> 作為副檔名的命名方式(不過也越來越普遍了)。
	    <command>gcc</command> 會依副檔名來決定用哪一種編譯器編譯,
	    然而,現在已經不再限制副檔名了,
	    所以可以自由的使用 <filename>.cpp</filename> 作為 C++ 程式碼的副檔名!</para>
	</listitem>
      </varlistentry>
    </variablelist>

    <sect2>
      <title>常見的 <command>cc</command> 問題</title>

      <qandaset>
	<qandaentry>
	  <question>
	    <para>我用 <function>sin()</function> 函示撰寫我的程式,
	      但是有個錯誤訊息(如下),這代表著?</para>

	    <informalexample>
	      <screen>/var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment
	      </screen>
	    </informalexample>
	  </question>

	  <answer>
	    <para>當使用 <function>sin()</function> 這類的數學函示時,
	      你必須告訴 cc 要和數學函式庫作連結(linking),就像這樣:</para>

	    <informalexample>
	      <screen>&prompt.user; <userinput>cc -o foobar foobar.c -lm</userinput>
	      </screen>
	    </informalexample>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>好吧,我試著寫些簡單的程式,來練習使用 -lm 選項(該程式會運算 2.16 次方)</para>

	    <informalexample>
	      <programlisting>#include &lt;stdio.h&gt;

int main() {
	float f;

	f = pow(2.1, 6);
	printf("2.1 ^ 6 = %f\n", f);
	return 0;
}
	      </programlisting>
	    </informalexample>

	    <para>然後進行編譯:</para>

	    <informalexample>
	      <screen>&prompt.user; <userinput>cc temp.c -lm</userinput>
	      </screen>
	    </informalexample>

	    <para>編譯後執行程式,得到下面這結果:</para>

	    <informalexample>
	      <screen>&prompt.user; <userinput>./a.out</userinput>
2.1 ^ 6 = 1023.000000
	      </screen>
	    </informalexample>

	    <para>很明顯的,程式結果<emphasis>不是</emphasis>正確答案,到底是哪邊出錯?</para>
	  </question>

	  <answer>
	    <para>當編譯器發現你呼叫一個函示時,它會確認該函示的回傳值類型(prototype),
	      如果沒有特別指明,則預設的回傳值類型為 <type>int(整數)</type>。
	      很明顯的,你的程式所需要的並不是回傳值類別為 <type>int</type></para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>那如何才可以修正剛所說的問題?</para>
	  </question>

	  <answer>
	    <para>數學函示的回傳值類型(prototype)會定義在 <filename>math.h</filename>,
	      如果你有 include 這檔,編譯器就會知道該函示的回傳值類型,如此一來該運算就會得到正確的結果!</para>

	    <informalexample>
	      <programlisting>#include &lt;math.h&gt;
#include &lt;stdio.h&gt;

int main() {
...
	      </programlisting>
	    </informalexample>

	    <para>加了上述內容之後,再重新編譯,最後執行:</para>

	    <informalexample>
	      <screen>&prompt.user; <userinput>./a.out</userinput>
2.1 ^ 6 = 85.766121
	      </screen>
	    </informalexample>

	    <para>如果有用到數學函式,<emphasis>請確定</emphasis>要有 include <filename>math.h</filename> 這檔,
	      而且記得要和數學函式庫作連結。</para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>已經編譯好 <filename>foobar.c</filename>,
	      但是編譯後找不到 <filename>foobar</filename> 執行檔。 該去哪邊找呢?</para>
	  </question>

	  <answer>
	    <para>記得,除非有指定編譯結果的執行檔檔名,否則預設的執行檔檔名是 a.out。
	      用 <option>-o&nbsp;<replaceable>filename</replaceable></option> 參數,
	      就可以達到所想要的結果,比如:</para>

	    <informalexample>
	      <screen>&prompt.user; <userinput>cc -o foobar foobar.c</userinput>
	      </screen>
	    </informalexample>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>好,有個編譯好的程式叫做 <filename>foobar</filename>,
	      用 <command>ls</command> 指令時可以看到,
	      但執行時,訊息卻說卻沒有這檔案。為什麼?</para>
	  </question>

	  <answer>
	    <para>與 &ms-dos; 不同的是,除非有指定執行檔的路徑,
	      否則 &unix; 系統並不會在目前的目錄下尋找你想執行的檔案。
	      在指令列下打 <command>./foobar</command> 代表
	      <quote>執行在這個目錄底下名為 <filename>foobar</filename> 的程式</quote>,
	      或者也可以更改 <envar>PATH</envar> 環境變數設定如下,以達成類似效果:</para>

	    <informalexample>
	      <screen>bin:/usr/bin:/usr/local/bin:.
	      </screen>
	    </informalexample>

	    <para>上一行最後的 "." 代表<quote>如果在前面寫的其他目錄找不到,就找目前的目錄</quote></para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>試著執行 <filename>test</filename> 執行檔,
	      但是卻沒有任何事發生,到底是哪裡出錯了?</para>
	  </question>

	  <answer>
	    <para>大多數的 &unix; 系統都會在路徑 <filename>/usr/bin</filename> 擺放執行檔。
	      除非有指定使用在目前目錄內的 <filename>test</filename>,否則 shell 會優先選擇位在
	      <filename>/usr/bin</filename><filename>test</filename>,
	      要指定檔名的話,作法類似:</para>

	    <informalexample>
	      <screen>&prompt.user; <userinput>./test</userinput>
	      </screen>
	    </informalexample>

	    <para>為了避免上述困擾,請為你的程式取更好的名稱吧!</para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>當執行我寫的程式時剛開始正常,
	      接下來卻出現 <errorname>core dumped</errorname> 錯誤訊息。這錯誤訊息到底代表什麼?</para>
	  </question>

	  <answer>
	    <para>關於 <firstterm>core dumped</firstterm> 這個名稱的由來,
	      可以追溯到早期的 &unix; 系統開始使用 core memory 對資料排序時。
	      基本上當程式在很多情況下發生錯誤後,
	      作業系統會把 core memory 中的資訊寫入 <filename>core</filename> 這檔案中,
	      以便讓 programmer 知道程式到底是為何出錯。</para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>真是太神奇了!程式居然發生 <errorname>core dumped</errorname> 了,該怎麼辦?</para>
	  </question>

	  <answer>
	    <para>請用 <command>gdb</command> 來分析 core 結果(詳情請參考 <xref linkend="debugging"/>)。</para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>當程式已經把 core memory 資料 dump 出來後,
	      同時也出現另一個錯誤 <errorname>segmentation fault</errorname> 這意思是?</para>
	  </question>

	  <answer>
	    <para>基本上,這個錯誤表示你的程式在記憶體中試著做一個嚴重的非法運作(illegal operation),
	      &unix; 就是被設計來保護整個作業系統免於被惡質的程式破壞,所以才會告訴你這個訊息。</para>

	    <para>最常造成<quote>segmentation fault</quote>的原因通常為:</para>

	    <itemizedlist>
	      <listitem>
		<para>試著對一個 <symbol>NULL</symbol> 的指標(pointer)作寫入的動作,如</para>

		<programlisting>char *foo = NULL;
strcpy(foo, "bang!");
		</programlisting>
	      </listitem>

	      <listitem>
		<para>使用一個尚未初始化(initialized)的指標,如:</para>

		<programlisting>char *foo;
strcpy(foo, "bang!");
		</programlisting>

		<para>尚未初始化的指標的初始值將會是隨機的,如果你夠幸運的話,
		  這個指標的初始值會指向 kernel 已經用到的記憶體位置,
		  kernel 會結束掉這個程式以確保系統運作正常。如果你不夠幸運,
		  初始指到的記憶體位置是你程式必須要用到的資料結構(data structures)的位置,
		  當這個情形發生時程式將會當的不知其所以然。</para>
	      </listitem>

	      <listitem>
		<para>試著寫入超過陣列(array)元素個數,如:</para>

		<programlisting>int bar[20];
bar[27] = 6;
		</programlisting>
	      </listitem>

	      <listitem>
		<para>試著讀寫在唯讀記憶體(read-only memory)中的資料,如:</para>

		<programlisting>char *foo = "My string";
strcpy(foo, "bang!");
		</programlisting>

		<para>&unix; compilers often put string literals like
		  <literal>"My string"</literal> into read-only areas
		  of memory.</para>
	      </listitem>

	      <listitem>
		<para>Doing naughty things with
		  <function>malloc()</function> and
		  <function>free()</function>, eg</para>

		<programlisting>char bar[80];
free(bar);
		</programlisting>

		<para>or</para>

		<programlisting>char *foo = malloc(27);
free(foo);
free(foo);
		</programlisting>
	      </listitem>
	    </itemizedlist>

	    <para>Making one of these mistakes will not always lead to
	      an error, but they are always bad practice.  Some
	      systems and compilers are more tolerant than others,
	      which is why programs that ran well on one system can
	      crash when you try them on an another.</para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>Sometimes when I get a core dump it says
	      <errorname>bus error</errorname>.  It says in my &unix;
	      book that this means a hardware problem, but the
	      computer still seems to be working.  Is this
	      true?</para>
	  </question>

	  <answer>
	    <para>No, fortunately not (unless of course you really do
	      have a hardware problem&hellip;).  This is usually
	      another way of saying that you accessed memory in a way
	      you should not have.</para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>This dumping core business sounds as though it could
	      be quite useful, if I can make it happen when I want to.
	      Can I do this, or do I have to wait until there is an
	      error?</para>
	  </question>

	  <answer>
	    <para>Yes, just go to another console or xterm, do</para>

	    <screen>&prompt.user; <userinput>ps</userinput>
	    </screen>

	    <para>to find out the process ID of your program, and
	      do</para>

	    <screen>&prompt.user; <userinput>kill -ABRT pid</userinput>
	    </screen>

	    <para>where
	      <parameter><replaceable>pid</replaceable></parameter> is
	      the process ID you looked up.</para>

	    <para>This is useful if your program has got stuck in an
	      infinite loop, for instance.  If your program happens to
	      trap <symbol>SIGABRT</symbol>, there are several other
	      signals which have a similar effect.</para>

	    <para>Alternatively, you can create a core dump from
	      inside your program, by calling the
	      <function>abort()</function> function. See the manual page
	      of &man.abort.3; to learn more.</para>

            <para>If you want to create a core dump from outside your
              program, but do not want the process to terminate, you
              can use the <command>gcore</command> program. See the
              manual page of &man.gcore.1; for more information.</para>

	  </answer>
	</qandaentry>
      </qandaset>
    </sect2>
  </sect1>

  <sect1 xml:id="tools-make">
    <title>Make</title>

    <sect2>
      <title>What is <command>make</command>?</title>

      <para>When you are working on a simple program with only one or
	two source files, typing in</para>

      <screen>&prompt.user; <userinput>cc file1.c file2.c</userinput></screen>

      <para>is not too bad, but it quickly becomes very tedious when
	there are several files&mdash;and it can take a while to
	compile, too.</para>

      <para>One way to get around this is to use object files and only
	recompile the source file if the source code has changed.  So
	we could have something like:</para>

      <screen>&prompt.user; <userinput>cc file1.o file2.o</userinput> &hellip; <userinput>file37.c</userinput> &hellip;</screen>

      <para>if we had changed <filename>file37.c</filename>, but not any
	of the others, since the last time we compiled.  This may
	speed up the compilation quite a bit, but does not solve the
	typing problem.</para>

      <para>Or we could write a shell script to solve the typing
	problem, but it would have to re-compile everything, making it
	very inefficient on a large project.</para>

      <para>What happens if we have hundreds of source files lying
	about? What if we are working in a team with other people who
	forget to tell us when they have changed one of their source
	files that we use?</para>

      <para>Perhaps we could put the two solutions together and write
	something like a shell script that would contain some kind of
	magic rule saying when a source file needs compiling.  Now all
	we need now is a program that can understand these rules, as
	it is a bit too complicated for the shell.</para>

      <para>This program is called <command>make</command>.  It reads
	in a file, called a <firstterm>makefile</firstterm>, that
	tells it how different files depend on each other, and works
	out which files need to be re-compiled and which ones do not.
	For example, a rule could say something like <quote>if
	  <filename>fromboz.o</filename> is older than
	  <filename>fromboz.c</filename>, that means someone must have
	  changed <filename>fromboz.c</filename>, so it needs to be
	  re-compiled.</quote> The makefile also has rules telling
	make <emphasis>how</emphasis> to re-compile the source file,
	making it a much more powerful tool.</para>

      <para>Makefiles are typically kept in the same directory as the
	source they apply to, and can be called
	<filename>makefile</filename>, <filename>Makefile</filename>
	or <filename>MAKEFILE</filename>.  Most programmers use the
	name <filename>Makefile</filename>, as this puts it near the
	top of a directory listing, where it can easily be
	seen.

	<footnote>
	  <para>They do not use the <filename>MAKEFILE</filename> form
	    as block capitals are often used for documentation files
	    like <filename>README</filename>.</para>
	</footnote></para>
    </sect2>

    <sect2>
      <title>Example of using <command>make</command></title>

      <para>Here is a very simple make file:</para>

      <programlisting>foo: foo.c
	cc -o foo foo.c</programlisting>

      <para>It consists of two lines, a dependency line and a creation
	line.</para>

      <para>The dependency line here consists of the name of the
	program (known as the <firstterm>target</firstterm>), followed
	by a colon, then whitespace, then the name of the source file.
	When <command>make</command> reads this line, it looks to see
	if <filename>foo</filename> exists; if it exists, it compares
	the time <filename>foo</filename> was last modified to the
	time <filename>foo.c</filename> was last modified.  If
	<filename>foo</filename> does not exist, or is older than
	<filename>foo.c</filename>, it then looks at the creation line
	to find out what to do.  In other words, this is the rule for
	working out when <filename>foo.c</filename> needs to be
	re-compiled.</para>

      <para>The creation line starts with a <token>tab</token> (press
	the <keycap>tab</keycap> key) and then the command you would
	type to create <filename>foo</filename> if you were doing it
	at a command prompt.  If <filename>foo</filename> is out of
	date, or does not exist, <command>make</command> then executes
	this command to create it.  In other words, this is the rule
	which tells make how to re-compile
	<filename>foo.c</filename>.</para>

      <para>So, when you type <userinput>make</userinput>, it will
	make sure that <filename>foo</filename> is up to date with
	respect to your latest changes to <filename>foo.c</filename>.
	This principle can be extended to
	<filename>Makefile</filename>s with hundreds of
	targets&mdash;in fact, on FreeBSD, it is possible to compile
	the entire operating system just by typing <userinput>make
	  world</userinput> in the appropriate directory!</para>

      <para>Another useful property of makefiles is that the targets
	do not have to be programs.  For instance, we could have a make
	file that looks like this:</para>

      <programlisting>foo: foo.c
	cc -o foo foo.c

install:
	cp foo /home/me</programlisting>

      <para>We can tell make which target we want to make by
	typing:</para>

      <screen>&prompt.user; <userinput>make target</userinput></screen>

      <para><command>make</command> will then only look at that target
	and ignore any others.  For example, if we type
	<userinput>make foo</userinput> with the makefile above, make
	will ignore the <buildtarget>install</buildtarget> target.</para>

      <para>If we just type <userinput>make</userinput> on its own,
	make will always look at the first target and then stop
	without looking at any others.  So if we typed
	<userinput>make</userinput> here, it will just go to the
	<buildtarget>foo</buildtarget> target, re-compile
	<filename>foo</filename> if necessary, and then stop without
	going on to the <buildtarget>install</buildtarget> target.</para>

      <para>Notice that the <buildtarget>install</buildtarget> target does not
	actually depend on anything! This means that the command on
	the following line is always executed when we try to make that
	target by typing <userinput>make install</userinput>.  In this
	case, it will copy <filename>foo</filename> into the user's
	home directory.  This is often used by application makefiles,
	so that the application can be installed in the correct
	directory when it has been correctly compiled.</para>

      <para>This is a slightly confusing subject to try to explain.
	If you do not quite understand how <command>make</command>
	works, the best thing to do is to write a simple program like
	<quote>hello world</quote> and a make file like the one above
	and experiment.  Then progress to using more than one source
	file, or having the source file include a header file.  The
	<command>touch</command> command is very useful here&mdash;it
	changes the date on a file without you having to edit
	it.</para>
    </sect2>

    <sect2>
      <title>Make and include-files</title>

      <para>C code often starts with a list of files to include, for
	example stdio.h. Some of these files are system-include
	files, some of them are from the project you are now working
	on:
      </para>

      <programlisting>#include &lt;stdio.h&gt;
#include "foo.h"

int main(....</programlisting>

      <para>To make sure that this file is recompiled the moment
        <filename>foo.h</filename> is changed, you have to add it in
        your <filename>Makefile</filename>:</para>

      <programlisting>foo: foo.c foo.h</programlisting>

      <para>The moment your project is getting bigger and you have
	more and more own include-files to maintain, it will be a
	pain to keep track of all include files and the files which
	are depending on it. If you change an include-file but
	forget to recompile all the files which are depending on
	it, the results will be devastating. <command>gcc</command>
	has an option to analyze your files and to produce a list
	of include-files and their dependencies: <option>-MM</option>.
      </para>

      <para>If you add this to your Makefile:</para>

      <programlisting>depend:
	gcc -E -MM *.c &gt; .depend</programlisting>

      <para>and run <userinput>make depend</userinput>, the file
	<filename>.depend</filename> will appear with a list of
	object-files, C-files and the include-files:</para>

      <programlisting>foo.o: foo.c foo.h</programlisting>

      <para>If you change <filename>foo.h</filename>, next time
	you run <command>make</command> all files depending on
	<filename>foo.h</filename> will be recompiled.</para>

      <para>Do not forget to run <command>make depend</command> each
        time you add an include-file to one of your files.</para>
    </sect2>

    <sect2>
      <title>FreeBSD Makefiles</title>

      <para>Makefiles can be rather complicated to write.  Fortunately,
	BSD-based systems like FreeBSD come with some very powerful
	ones as part of the system.  One very good example of this is
	the FreeBSD ports system.  Here is the essential part of a
	typical ports <filename>Makefile</filename>:</para>

      <programlisting>MASTER_SITES=   ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/
DISTFILES=      scheme-microcode+dist-7.3-freebsd.tgz

.include &lt;bsd.port.mk&gt;</programlisting>

      <para>Now, if we go to the directory for this port and type
	<userinput>make</userinput>, the following happens:</para>

      <procedure>
	<step>
	  <para>A check is made to see if the source code for this
	    port is already on the system.</para>
	</step>

	<step>
	  <para>If it is not, an FTP connection to the URL in
	    <symbol>MASTER_SITES</symbol> is set up to download the
	    source.</para>
	</step>

	<step>
	  <para>The checksum for the source is calculated and compared
	    it with one for a known, good, copy of the source.  This
	    is to make sure that the source was not corrupted while in
	    transit.</para>
	</step>

	<step>
	  <para>Any changes required to make the source work on
	    FreeBSD are applied&mdash;this is known as
	    <firstterm>patching</firstterm>.</para>
	</step>

	<step>
	  <para>Any special configuration needed for the source is
	    done.  (Many &unix; program distributions try to work out
	    which version of &unix; they are being compiled on and which
	    optional &unix; features are present&mdash;this is where
	    they are given the information in the FreeBSD ports
	    scenario).</para>
	</step>

	<step>
	  <para>The source code for the program is compiled.  In
	    effect, we change to the directory where the source was
	    unpacked and do <command>make</command>&mdash;the
	    program's own make file has the necessary information to
	    build the program.</para>
	</step>

	<step>
	  <para>We now have a compiled version of the program.  If we
	    wish, we can test it now; when we feel confident about the
	    program, we can type <userinput>make install</userinput>.
	    This will cause the program and any supporting files it
	    needs to be copied into the correct location; an entry is
	    also made into a <database>package database</database>, so
	    that the port can easily be uninstalled later if we change
	    our mind about it.</para>
	</step>
      </procedure>

      <para>Now I think you will agree that is rather impressive for a
	four line script!</para>

      <para>The secret lies in the last line, which tells
	<command>make</command> to look in the system makefile called
	<filename>bsd.port.mk</filename>.  It is easy to overlook this
	line, but this is where all the clever stuff comes
	from&mdash;someone has written a makefile that tells
	<command>make</command> to do all the things above (plus a
	couple of other things I did not mention, including handling
	any errors that may occur) and anyone can get access to that
	just by putting a single line in their own make file!</para>

      <para>If you want to have a look at these system makefiles,
	they are in <filename>/usr/share/mk</filename>, but it is
	probably best to wait until you have had a bit of practice with
	makefiles, as they are very complicated (and if you do look at
	them, make sure you have a flask of strong coffee
	handy!)</para>
    </sect2>

    <sect2>
      <title>More advanced uses of <command>make</command></title>

      <para><command>Make</command> is a very powerful tool, and can
	do much more than the simple example above shows.
	Unfortunately, there are several different versions of
	<command>make</command>, and they all differ considerably.
	The best way to learn what they can do is probably to read the
	documentation&mdash;hopefully this introduction will have
	given you a base from which you can do this.</para>

      <para>The version of make that comes with FreeBSD is the
	<application>Berkeley make</application>; there is a tutorial
	for it in <filename>/usr/share/doc/psd/12.make</filename>.  To
	view it, do</para>

      <screen>&prompt.user; <userinput>zmore paper.ascii.gz</userinput></screen>

      <para>in that directory.</para>

      <para>Many applications in the ports use <application>GNU
	  make</application>, which has a very good set of
	<quote>info</quote> pages.  If you have installed any of these
	ports, <application>GNU make</application> will automatically
	have been installed as <command>gmake</command>.  It is also
	available as a port and package in its own right.</para>

      <para>To view the info pages for <application>GNU
	make</application>, you will have to edit the
	<filename>dir</filename> file in the
	<filename>/usr/local/info</filename> directory to add an entry
	for it.  This involves adding a line like</para>

      <programlisting> * Make: (make).                 The GNU Make utility.</programlisting>

      <para>to the file.  Once you have done this, you can type
	<userinput>info</userinput> and then select
	<guimenuitem>make</guimenuitem> from the menu (or in
	<application>Emacs</application>, do <userinput>C-h
	  i</userinput>).</para>
    </sect2>
  </sect1>

  <sect1 xml:id="debugging">
    <title>Debugging</title>

    <sect2>
      <title>The Debugger</title>

      <para>The debugger that comes with FreeBSD is called
	<command>gdb</command> (<application>GNU
	  debugger</application>).  You start it up by typing</para>

      <screen>&prompt.user; <userinput>gdb progname</userinput></screen>

      <para>although most people prefer to run it inside
	<application>Emacs</application>.  You can do this by:</para>

      <screen><userinput>M-x gdb RET progname RET</userinput></screen>

      <para>Using a debugger allows you to run the program under more
	controlled circumstances.  Typically, you can step through the
	program a line at a time, inspect the value of variables,
	change them, tell the debugger to run up to a certain point
	and then stop, and so on.  You can even attach to a program
	that is already running, or load a core file to investigate why
	the program crashed.  It is even possible to debug the kernel,
	though that is a little trickier than the user applications
	we will be discussing in this section.</para>

      <para><command>gdb</command> has quite good on-line help, as
	well as a set of info pages, so this section will concentrate
	on a few of the basic commands.</para>

      <para>Finally, if you find its text-based command-prompt style
	off-putting, there is a graphical front-end for it (<link xlink:href="&url.base;/ports/devel.html">xxgdb</link>) in the ports
	collection.</para>

      <para>This section is intended to be an introduction to using
	<command>gdb</command> and does not cover specialized topics
	such as debugging the kernel.</para>
    </sect2>

    <sect2>
      <title>Running a program in the debugger</title>

      <para>You will need to have compiled the program with the
	<option>-g</option> option to get the most out of using
	<command>gdb</command>.  It will work without, but you will only
	see the name of the function you are in, instead of the source
	code.  If you see a line like:</para>

      <screen>&hellip; (no debugging symbols found) &hellip;</screen>

      <para>when <command>gdb</command> starts up, you will know that
	the program was not compiled with the <option>-g</option>
	option.</para>

      <para>At the <command>gdb</command> prompt, type
	<userinput>break main</userinput>.  This will tell the
	debugger to skip over the preliminary set-up code in the
	program and start at the beginning of your code.  Now type
	<userinput>run</userinput> to start the program&mdash;it will
	start at the beginning of the set-up code and then get stopped
	by the debugger when it calls <function>main()</function>.
	(If you have ever wondered where <function>main()</function>
	gets called from, now you know!).</para>

      <para>You can now step through the program, a line at a time, by
	pressing <command>n</command>.  If you get to a function call,
	you can step into it by pressing <command>s</command>.  Once
	you are in a function call, you can return from stepping into a
	function call by pressing <command>f</command>.  You can also
	use <command>up</command> and <command>down</command> to take
	a quick look at the caller.</para>

      <para>Here is a simple example of how to spot a mistake in a
	program with <command>gdb</command>.  This is our program
	(with a deliberate mistake):</para>

      <programlisting>#include &lt;stdio.h&gt;

int bazz(int anint);

main() {
	int i;

	printf("This is my program\n");
	bazz(i);
	return 0;
}

int bazz(int anint) {
	printf("You gave me %d\n", anint);
	return anint;
}</programlisting>

      <para>This program sets <symbol>i</symbol> to be
	<literal>5</literal> and passes it to a function
	<function>bazz()</function> which prints out the number we
	gave it.</para>

      <para>When we compile and run the program we get</para>

      <screen>&prompt.user; <userinput>cc -g -o temp temp.c</userinput>
&prompt.user; <userinput>./temp</userinput>
This is my program
anint = 4231</screen>

      <para>That was not what we expected! Time to see what is going
	on!</para>

      <screen>&prompt.user; <userinput>gdb temp</userinput>
GDB is free software and you are welcome to distribute copies of it
 under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc.
(gdb) <userinput>break main</userinput>				<lineannotation>Skip the set-up code</lineannotation>
Breakpoint 1 at 0x160f: file temp.c, line 9.	<lineannotation>gdb puts breakpoint at main()</lineannotation>
(gdb) <userinput>run</userinput>					<lineannotation>Run as far as main()</lineannotation>
Starting program: /home/james/tmp/temp		<lineannotation>Program starts running</lineannotation>

Breakpoint 1, main () at temp.c:9		<lineannotation>gdb stops at main()</lineannotation>
(gdb) <userinput>n</userinput>						<lineannotation>Go to next line</lineannotation>
This is my program				<lineannotation>Program prints out</lineannotation>
(gdb) <userinput>s</userinput>						<lineannotation>step into bazz()</lineannotation>
bazz (anint=4231) at temp.c:17			<lineannotation>gdb displays stack frame</lineannotation>
(gdb)</screen>

      <para>Hang on a minute! How did <symbol>anint</symbol> get to be
	<literal>4231</literal>? Did we not we set it to be
	<literal>5</literal> in <function>main()</function>? Let's
	move up to <function>main()</function> and have a look.</para>

      <screen>(gdb) <userinput>up</userinput>					<lineannotation>Move up call stack</lineannotation>
#1  0x1625 in main () at temp.c:11		<lineannotation>gdb displays stack frame</lineannotation>
(gdb) <userinput>p i</userinput>					<lineannotation>Show us the value of i</lineannotation>
$1 = 4231					<lineannotation>gdb displays 4231</lineannotation></screen>

      <para>Oh dear! Looking at the code, we forgot to initialize
	<symbol>i</symbol>.  We meant to put</para>

      <programlisting><lineannotation>&hellip;</lineannotation>
main() {
	int i;

	i = 5;
	printf("This is my program\n");
<lineannotation>&hellip;</lineannotation></programlisting>

      <para>but we left the <literal>i=5;</literal> line out.  As we
	did not initialize <symbol>i</symbol>, it had whatever number
	happened to be in that area of memory when the program ran,
	which in this case happened to be
	<literal>4231</literal>.</para>

      <note>
	<para><command>gdb</command> displays the stack frame every
	  time we go into or out of a function, even if we are using
	  <command>up</command> and <command>down</command> to move
	  around the call stack.  This shows the name of the function
	  and the values of its arguments, which helps us keep track
	  of where we are and what is going on.  (The stack is a
	  storage area where the program stores information about the
	  arguments passed to functions and where to go when it
	  returns from a function call).</para>
      </note>
    </sect2>

    <sect2>
      <title>Examining a core file</title>

      <para>A core file is basically a file which contains the
	complete state of the process when it crashed.  In <quote>the
	  good old days</quote>, programmers had to print out hex
	listings of core files and sweat over machine code manuals,
	but now life is a bit easier.  Incidentally, under FreeBSD and
	other 4.4BSD systems, a core file is called
	<filename>progname.core</filename> instead of just
	<filename>core</filename>, to make it clearer which program a
	core file belongs to.</para>

      <para>To examine a core file, start up <command>gdb</command> in
	the usual way.  Instead of typing <command>break</command> or
	<command>run</command>, type</para>

      <screen>(gdb) <userinput>core progname.core</userinput></screen>

      <para>If you are not in the same directory as the core file,
	you will have to do <userinput>dir
	  /path/to/core/file</userinput> first.</para>

      <para>You should see something like this:</para>

      <screen>&prompt.user; <userinput>gdb a.out</userinput>
GDB is free software and you are welcome to distribute copies of it
 under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc.
(gdb) <userinput>core a.out.core</userinput>
Core was generated by `a.out'.
Program terminated with signal 11, Segmentation fault.
Cannot access memory at address 0x7020796d.
#0  0x164a in bazz (anint=0x5) at temp.c:17
(gdb)</screen>

      <para>In this case, the program was called
	<filename>a.out</filename>, so the core file is called
	<filename>a.out.core</filename>.  We can see that the program
	crashed due to trying to access an area in memory that was not
	available to it in a function called
	<function>bazz</function>.</para>

      <para>Sometimes it is useful to be able to see how a function was
	called, as the problem could have occurred a long way up the
	call stack in a complex program.  The <command>bt</command>
	command causes <command>gdb</command> to print out a
	back-trace of the call stack:</para>

      <screen>(gdb) <userinput>bt</userinput>
#0  0x164a in bazz (anint=0x5) at temp.c:17
#1  0xefbfd888 in end ()
#2  0x162c in main () at temp.c:11
(gdb)</screen>

      <para>The <function>end()</function> function is called when a
	program crashes; in this case, the <function>bazz()</function>
	function was called from <function>main()</function>.</para>
    </sect2>

    <sect2>
      <title>Attaching to a running program</title>

      <para>One of the neatest features about <command>gdb</command>
	is that it can attach to a program that is already running.  Of
	course, that assumes you have sufficient permissions to do so.
	A common problem is when you are stepping through a program
	that forks, and you want to trace the child, but the debugger
	will only let you trace the parent.</para>

      <para>What you do is start up another <command>gdb</command>,
	use <command>ps</command> to find the process ID for the
	child, and do</para>

      <screen>(gdb) <userinput>attach pid</userinput></screen>

      <para>in <command>gdb</command>, and then debug as usual.</para>

      <para><quote>That is all very well,</quote> you are probably
	thinking, <quote>but by the time I have done that, the child
	  process will be over the hill and far away</quote>.  Fear
	not, gentle reader, here is how to do it (courtesy of the
	<command>gdb</command> info pages):</para>

      <screen><lineannotation>&hellip;</lineannotation>
if ((pid = fork()) &lt; 0)		/* _Always_ check this */
	error();
else if (pid == 0) {		/* child */
	int PauseMode = 1;

	while (PauseMode)
		sleep(10);	/* Wait until someone attaches to us */
	<lineannotation>&hellip;</lineannotation>
} else {			/* parent */
	<lineannotation>&hellip;</lineannotation></screen>

      <para>Now all you have to do is attach to the child, set
	<symbol>PauseMode</symbol> to <literal>0</literal>, and wait
	for the <function>sleep()</function> call to return!</para>
    </sect2>
  </sect1>

  <sect1 xml:id="emacs">
    <title>Using Emacs as a Development Environment</title>

    <sect2>
      <title>Emacs</title>

      <para>Unfortunately, &unix; systems do not come with the kind of
	everything-you-ever-wanted-and-lots-more-you-did-not-in-one-gigantic-package
	integrated development environments that other systems
	have.

	<footnote>
	  <para>Some powerful, free IDEs now exist, such as KDevelop
	    in the ports collection.</para>
	</footnote>

	However, it is possible to set up your own environment.  It
	may not be as pretty, and it may not be quite as integrated,
	but you can set it up the way you want it.  And it is free.
	And you have the source to it.</para>

      <para>The key to it all is Emacs.  Now there are some people who
	loathe it, but many who love it.  If you are one of the former,
	I am afraid this section will hold little of interest to you.
	Also, you will need a fair amount of memory to run it&mdash;I would
	recommend 8MB in text mode and 16MB in X as the bare minimum
	to get reasonable performance.</para>

      <para>Emacs is basically a highly customizable
	editor&mdash;indeed, it has been customized to the point where
	it is more like an operating system than an editor! Many
	developers and sysadmins do in fact spend practically all
	their time working inside Emacs, leaving it only to log
	out.</para>

      <para>It is impossible even to summarize everything Emacs can do
	here, but here are some of the features of interest to
	developers:</para>

      <itemizedlist>
	<listitem>
	  <para>Very powerful editor, allowing search-and-replace on
	    both strings and regular expressions (patterns), jumping
	    to start/end of block expression, etc, etc.</para>
	</listitem>

	<listitem>
	  <para>Pull-down menus and online help.</para>
	</listitem>

	<listitem>
	  <para>Language-dependent syntax highlighting and
	    indentation.</para>
	</listitem>

	<listitem>
	  <para>Completely customizable.</para>
	</listitem>

	<listitem>
	  <para>You can compile and debug programs within
	    Emacs.</para>
	</listitem>

	<listitem>
	  <para>On a compilation error, you can jump to the offending
	    line of source code.</para>
	</listitem>

	<listitem>
	  <para>Friendly-ish front-end to the <command>info</command>
	    program used for reading GNU hypertext documentation,
	    including the documentation on Emacs itself.</para>
	</listitem>

	<listitem>
	  <para>Friendly front-end to <command>gdb</command>, allowing
	    you to look at the source code as you step through your
	    program.</para>
	</listitem>

	<listitem>
	  <para>You can read Usenet news and mail while your program
	    is compiling.</para>
	</listitem>
      </itemizedlist>

      <para>And doubtless many more that I have overlooked.</para>

      <para>Emacs can be installed on FreeBSD using <link xlink:href="&url.base;/ports/editors.html">the Emacs
	  port</link>.</para>

      <para>Once it is installed, start it up and do <userinput>C-h
	  t</userinput> to read an Emacs tutorial&mdash;that means
	hold down the <keycap>control</keycap> key, press
	<keycap>h</keycap>, let go of the <keycap>control</keycap>
	key, and then press <keycap>t</keycap>.  (Alternatively, you
	can you use the mouse to select <guimenuitem>Emacs
	  Tutorial</guimenuitem> from the <guimenu>Help</guimenu>
	menu).</para>

      <para>Although Emacs does have menus, it is well worth learning
	the key bindings, as it is much quicker when you are editing
	something to press a couple of keys than to try to find the
	mouse and then click on the right place.  And, when you are
	talking to seasoned Emacs users, you will find they often
	casually throw around expressions like <quote><literal>M-x
	    replace-s RET foo RET bar RET</literal></quote> so it is
	useful to know what they mean.  And in any case, Emacs has far
	too many useful functions for them to all fit on the menu
	bars.</para>

      <para>Fortunately, it is quite easy to pick up the key-bindings,
	as they are displayed next to the menu item.  My advice is to
	use the menu item for, say, opening a file until you
	understand how it works and feel confident with it, then try
	doing C-x C-f.  When you are happy with that, move on to
	another menu command.</para>

      <para>If you can not remember what a particular combination of
	keys does, select <guimenuitem>Describe Key</guimenuitem> from
	the <guimenu>Help</guimenu> menu and type it in&mdash;Emacs
	will tell you what it does.  You can also use the
	<guimenuitem>Command Apropos</guimenuitem> menu item to find
	out all the commands which contain a particular word in them,
	with the key binding next to it.</para>

      <para>By the way, the expression above means hold down the
	<keysym>Meta</keysym> key, press <keysym>x</keysym>, release
	the <keysym>Meta</keysym> key, type
	<userinput>replace-s</userinput> (short for
	<literal>replace-string</literal>&mdash;another feature of
	Emacs is that you can abbreviate commands), press the
	<keysym>return</keysym> key, type <userinput>foo</userinput>
	(the string you want replaced), press the
	<keysym>return</keysym> key, type bar (the string you want to
	replace <literal>foo</literal> with) and press
	<keysym>return</keysym> again.  Emacs will then do the
	search-and-replace operation you have just requested.</para>

      <para>If you are wondering what on earth the
	<keysym>Meta</keysym> key is, it is a special key that many
	&unix; workstations have.  Unfortunately, PC's do not have one,
	so it is usually the <keycap>alt</keycap> key (or if you are
	unlucky, the <keysym>escape</keysym> key).</para>

      <para>Oh, and to get out of Emacs, do <command>C-x C-c</command>
	(that means hold down the <keysym>control</keysym> key, press
	<keysym>x</keysym>, press <keysym>c</keysym> and release the
	<keysym>control</keysym> key).  If you have any unsaved files
	open, Emacs will ask you if you want to save them.  (Ignore
	the bit in the documentation where it says
	<command>C-z</command> is the usual way to leave
	Emacs&mdash;that leaves Emacs hanging around in the
	background, and is only really useful if you are on a system
	which does not have virtual terminals).</para>
    </sect2>

    <sect2>
      <title>Configuring Emacs</title>

      <para>Emacs does many wonderful things; some of them are built
	in, some of them need to be configured.</para>

      <para>Instead of using a proprietary macro language for
	configuration, Emacs uses a version of Lisp specially adapted
	for editors, known as Emacs Lisp.  Working with Emacs Lisp can
	be quite helpful if you want to go on and learn something like
	Common Lisp.  Emacs Lisp has many features of Common Lisp,
	although it is considerably smaller (and thus easier to
	master).</para>

      <para>The best way to learn Emacs Lisp is to download the <link xlink:href="ftp://ftp.gnu.org/old-gnu/emacs/elisp-manual-19-2.4.tar.gz">Emacs
	  Tutorial</link></para>

      <para>However, there is no need to actually know any Lisp to get
	started with configuring Emacs, as I have included a sample
	<filename>.emacs</filename> file, which should be enough to
	get you started.  Just copy it into your home directory and
	restart Emacs if it is already running; it will read the
	commands from the file and (hopefully) give you a useful basic
	setup.</para>
    </sect2>

    <sect2>
      <title>A sample <filename>.emacs</filename> file</title>

      <para>Unfortunately, there is far too much here to explain it in
	detail; however there are one or two points worth
	mentioning.</para>

      <itemizedlist>
	<listitem>
	  <para>Everything beginning with a <literal>;</literal> is a comment
	    and is ignored by Emacs.</para>
	</listitem>

	<listitem>
	  <para>In the first line, the
	    <literal>-*-&nbsp;Emacs-Lisp&nbsp;-*-</literal> is so that
	    we can edit the <filename>.emacs</filename> file itself
	    within Emacs and get all the fancy features for editing
	    Emacs Lisp.  Emacs usually tries to guess this based on
	    the filename, and may not get it right for
	    <filename>.emacs</filename>.</para>
	</listitem>

	<listitem>
	  <para>The <keysym>tab</keysym> key is bound to an
	    indentation function in some modes, so when you press the
	    tab key, it will indent the current line of code.  If you
	    want to put a <token>tab</token> character in whatever
	    you are writing, hold the <keysym>control</keysym> key down
	    while you are pressing the <keysym>tab</keysym> key.</para>
	</listitem>

	<listitem>
	  <para>This file supports syntax highlighting for C, C++,
	    Perl, Lisp and Scheme, by guessing the language from the
	    filename.</para>
	</listitem>

	<listitem>
	  <para>Emacs already has a pre-defined function called
	    <function>next-error</function>.  In a compilation output
	    window, this allows you to move from one compilation error
	    to the next by doing <command>M-n</command>; we define a
	    complementary function,
	    <function>previous-error</function>, that allows you to go
	    to a previous error by doing <command>M-p</command>.  The
	    nicest feature of all is that <command>C-c C-c</command>
	    will open up the source file in which the error occurred
	    and jump to the appropriate line.</para>
	</listitem>

	<listitem>
	  <para>We enable Emacs's ability to act as a server, so that
	    if you are doing something outside Emacs and you want to
	    edit a file, you can just type in</para>

	  <screen>&prompt.user; <userinput>emacsclient filename</userinput>
	  </screen>

	  <para>and then you can edit the file in your
	    Emacs!

	    <footnote>
	      <para>Many Emacs users set their <envar>EDITOR</envar>
		environment to
		<literal>emacsclient</literal> so this happens every
		time they need to edit a file.</para>
	    </footnote></para>
	</listitem>
      </itemizedlist>

      <example>
	<title>A sample <filename>.emacs</filename> file</title>

	<programlisting>;; -*-Emacs-Lisp-*-

;; This file is designed to be re-evaled; use the variable first-time
;; to avoid any problems with this.
(defvar first-time t
  "Flag signifying this is the first time that .emacs has been evaled")

;; Meta
(global-set-key "\M- " 'set-mark-command)
(global-set-key "\M-\C-h" 'backward-kill-word)
(global-set-key "\M-\C-r" 'query-replace)
(global-set-key "\M-r" 'replace-string)
(global-set-key "\M-g" 'goto-line)
(global-set-key "\M-h" 'help-command)

;; Function keys
(global-set-key [f1] 'manual-entry)
(global-set-key [f2] 'info)
(global-set-key [f3] 'repeat-complex-command)
(global-set-key [f4] 'advertised-undo)
(global-set-key [f5] 'eval-current-buffer)
(global-set-key [f6] 'buffer-menu)
(global-set-key [f7] 'other-window)
(global-set-key [f8] 'find-file)
(global-set-key [f9] 'save-buffer)
(global-set-key [f10] 'next-error)
(global-set-key [f11] 'compile)
(global-set-key [f12] 'grep)
(global-set-key [C-f1] 'compile)
(global-set-key [C-f2] 'grep)
(global-set-key [C-f3] 'next-error)
(global-set-key [C-f4] 'previous-error)
(global-set-key [C-f5] 'display-faces)
(global-set-key [C-f8] 'dired)
(global-set-key [C-f10] 'kill-compilation)

;; Keypad bindings
(global-set-key [up] "\C-p")
(global-set-key [down] "\C-n")
(global-set-key [left] "\C-b")
(global-set-key [right] "\C-f")
(global-set-key [home] "\C-a")
(global-set-key [end] "\C-e")
(global-set-key [prior] "\M-v")
(global-set-key [next] "\C-v")
(global-set-key [C-up] "\M-\C-b")
(global-set-key [C-down] "\M-\C-f")
(global-set-key [C-left] "\M-b")
(global-set-key [C-right] "\M-f")
(global-set-key [C-home] "\M-&lt;")
(global-set-key [C-end] "\M-&gt;")
(global-set-key [C-prior] "\M-&lt;")
(global-set-key [C-next] "\M-&gt;")

;; Mouse
(global-set-key [mouse-3] 'imenu)

;; Misc
(global-set-key [C-tab] "\C-q\t")	; Control tab quotes a tab.
(setq backup-by-copying-when-mismatch t)

;; Treat 'y' or &lt;CR&gt; as yes, 'n' as no.
(fset 'yes-or-no-p 'y-or-n-p)
(define-key query-replace-map [return] 'act)
(define-key query-replace-map [?\C-m] 'act)

;; Load packages
(require 'desktop)
(require 'tar-mode)

;; Pretty diff mode
(autoload 'ediff-buffers "ediff" "Intelligent Emacs interface to diff" t)
(autoload 'ediff-files "ediff" "Intelligent Emacs interface to diff" t)
(autoload 'ediff-files-remote "ediff"
  "Intelligent Emacs interface to diff")

(if first-time
    (setq auto-mode-alist
	  (append '(("\\.cpp$" . c++-mode)
		    ("\\.hpp$" . c++-mode)
		    ("\\.lsp$" . lisp-mode)
		    ("\\.scm$" . scheme-mode)
		    ("\\.pl$" . perl-mode)
		    ) auto-mode-alist)))

;; Auto font lock mode
(defvar font-lock-auto-mode-list
  (list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'lisp-mode 'perl-mode 'scheme-mode)
  "List of modes to always start in font-lock-mode")

(defvar font-lock-mode-keyword-alist
  '((c++-c-mode . c-font-lock-keywords)
    (perl-mode . perl-font-lock-keywords))
  "Associations between modes and keywords")

(defun font-lock-auto-mode-select ()
  "Automatically select font-lock-mode if the current major mode is in font-lock-auto-mode-list"
  (if (memq major-mode font-lock-auto-mode-list)
      (progn
	(font-lock-mode t))
    )
  )

(global-set-key [M-f1] 'font-lock-fontify-buffer)

;; New dabbrev stuff
;(require 'new-dabbrev)
(setq dabbrev-always-check-other-buffers t)
(setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_")
(add-hook 'emacs-lisp-mode-hook
	  '(lambda ()
	     (set (make-local-variable 'dabbrev-case-fold-search) nil)
	     (set (make-local-variable 'dabbrev-case-replace) nil)))
(add-hook 'c-mode-hook
	  '(lambda ()
	     (set (make-local-variable 'dabbrev-case-fold-search) nil)
	     (set (make-local-variable 'dabbrev-case-replace) nil)))
(add-hook 'text-mode-hook
	  '(lambda ()
	     (set (make-local-variable 'dabbrev-case-fold-search) t)
	     (set (make-local-variable 'dabbrev-case-replace) t)))

;; C++ and C mode...
(defun my-c++-mode-hook ()
  (setq tab-width 4)
  (define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent)
  (define-key c++-mode-map "\C-ce" 'c-comment-edit)
  (setq c++-auto-hungry-initial-state 'none)
  (setq c++-delete-function 'backward-delete-char)
  (setq c++-tab-always-indent t)
  (setq c-indent-level 4)
  (setq c-continued-statement-offset 4)
  (setq c++-empty-arglist-indent 4))

(defun my-c-mode-hook ()
  (setq tab-width 4)
  (define-key c-mode-map "\C-m" 'reindent-then-newline-and-indent)
  (define-key c-mode-map "\C-ce" 'c-comment-edit)
  (setq c-auto-hungry-initial-state 'none)
  (setq c-delete-function 'backward-delete-char)
  (setq c-tab-always-indent t)
;; BSD-ish indentation style
  (setq c-indent-level 4)
  (setq c-continued-statement-offset 4)
  (setq c-brace-offset -4)
  (setq c-argdecl-indent 0)
  (setq c-label-offset -4))

;; Perl mode
(defun my-perl-mode-hook ()
  (setq tab-width 4)
  (define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent)
  (setq perl-indent-level 4)
  (setq perl-continued-statement-offset 4))

;; Scheme mode...
(defun my-scheme-mode-hook ()
  (define-key scheme-mode-map "\C-m" 'reindent-then-newline-and-indent))

;; Emacs-Lisp mode...
(defun my-lisp-mode-hook ()
  (define-key lisp-mode-map "\C-m" 'reindent-then-newline-and-indent)
  (define-key lisp-mode-map "\C-i" 'lisp-indent-line)
  (define-key lisp-mode-map "\C-j" 'eval-print-last-sexp))

;; Add all of the hooks...
(add-hook 'c++-mode-hook 'my-c++-mode-hook)
(add-hook 'c-mode-hook 'my-c-mode-hook)
(add-hook 'scheme-mode-hook 'my-scheme-mode-hook)
(add-hook 'emacs-lisp-mode-hook 'my-lisp-mode-hook)
(add-hook 'lisp-mode-hook 'my-lisp-mode-hook)
(add-hook 'perl-mode-hook 'my-perl-mode-hook)

;; Complement to next-error
(defun previous-error (n)
  "Visit previous compilation error message and corresponding source code."
  (interactive "p")
  (next-error (- n)))

;; Misc...
(transient-mark-mode 1)
(setq mark-even-if-inactive t)
(setq visible-bell nil)
(setq next-line-add-newlines nil)
(setq compile-command "make")
(setq suggest-key-bindings nil)
(put 'eval-expression 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'set-goal-column 'disabled nil)
(if (&gt;= emacs-major-version 21)
	(setq show-trailing-whitespace t))

;; Elisp archive searching
(autoload 'format-lisp-code-directory "lispdir" nil t)
(autoload 'lisp-dir-apropos "lispdir" nil t)
(autoload 'lisp-dir-retrieve "lispdir" nil t)
(autoload 'lisp-dir-verify "lispdir" nil t)

;; Font lock mode
(defun my-make-face (face color &amp;optional bold)
  "Create a face from a color and optionally make it bold"
  (make-face face)
  (copy-face 'default face)
  (set-face-foreground face color)
  (if bold (make-face-bold face))
  )

(if (eq window-system 'x)
    (progn
      (my-make-face 'blue "blue")
      (my-make-face 'red "red")
      (my-make-face 'green "dark green")
      (setq font-lock-comment-face 'blue)
      (setq font-lock-string-face 'bold)
      (setq font-lock-type-face 'bold)
      (setq font-lock-keyword-face 'bold)
      (setq font-lock-function-name-face 'red)
      (setq font-lock-doc-string-face 'green)
      (add-hook 'find-file-hooks 'font-lock-auto-mode-select)

      (setq baud-rate 1000000)
      (global-set-key "\C-cmm" 'menu-bar-mode)
      (global-set-key "\C-cms" 'scroll-bar-mode)
      (global-set-key [backspace] 'backward-delete-char)
					;      (global-set-key [delete] 'delete-char)
      (standard-display-european t)
      (load-library "iso-transl")))

;; X11 or PC using direct screen writes
(if window-system
    (progn
      ;;      (global-set-key [M-f1] 'hilit-repaint-command)
      ;;      (global-set-key [M-f2] [?\C-u M-f1])
      (setq hilit-mode-enable-list
	    '(not text-mode c-mode c++-mode emacs-lisp-mode lisp-mode
		  scheme-mode)
	    hilit-auto-highlight nil
	    hilit-auto-rehighlight 'visible
	    hilit-inhibit-hooks nil
	    hilit-inhibit-rebinding t)
      (require 'hilit19)
      (require 'paren))
  (setq baud-rate 2400)			; For slow serial connections
  )

;; TTY type terminal
(if (and (not window-system)
	 (not (equal system-type 'ms-dos)))
    (progn
      (if first-time
	  (progn
	    (keyboard-translate ?\C-h ?\C-?)
	    (keyboard-translate ?\C-? ?\C-h)))))

;; Under UNIX
(if (not (equal system-type 'ms-dos))
    (progn
      (if first-time
	  (server-start))))

;; Add any face changes here
(add-hook 'term-setup-hook 'my-term-setup-hook)
(defun my-term-setup-hook ()
  (if (eq window-system 'pc)
      (progn
;;	(set-face-background 'default "red")
	)))

;; Restore the "desktop" - do this as late as possible
(if first-time
    (progn
      (desktop-load-default)
      (desktop-read)))

;; Indicate that this file has been read at least once
(setq first-time nil)

;; No need to debug anything now

(setq debug-on-error nil)

;; All done
(message "All done, %s%s" (user-login-name) ".")
	</programlisting>
      </example>
    </sect2>

    <sect2>
      <title>Extending the Range of Languages Emacs Understands</title>

      <para>Now, this is all very well if you only want to program in
	the languages already catered for in the
	<filename>.emacs</filename> file (C, C++, Perl, Lisp and
	Scheme), but what happens if a new language called
	<quote>whizbang</quote> comes out, full of exciting
	features?</para>

      <para>The first thing to do is find out if whizbang comes with
	any files that tell Emacs about the language.  These usually
	end in <filename>.el</filename>, short for <quote>Emacs
	  Lisp</quote>.  For example, if whizbang is a FreeBSD port, we
	can locate these files by doing</para>

      <screen>&prompt.user; <userinput>find /usr/ports/lang/whizbang -name "*.el" -print</userinput></screen>

      <para>and install them by copying them into the Emacs site Lisp
	directory.  On FreeBSD 2.1.0-RELEASE, this is
	<filename>/usr/local/share/emacs/site-lisp</filename>.</para>

      <para>So for example, if the output from the find command
	was</para>

      <screen>/usr/ports/lang/whizbang/work/misc/whizbang.el</screen>

      <para>we would do</para>

      <screen>&prompt.root; <userinput>cp /usr/ports/lang/whizbang/work/misc/whizbang.el /usr/local/share/emacs/site-lisp</userinput></screen>

      <para>Next, we need to decide what extension whizbang source
	files have.  Let's say for the sake of argument that they all
	end in <filename>.wiz</filename>.  We need to add an entry to
	our <filename>.emacs</filename> file to make sure Emacs will
	be able to use the information in
	<filename>whizbang.el</filename>.</para>

      <para>Find the <symbol>auto-mode-alist entry</symbol> in
	<filename>.emacs</filename> and add a line for whizbang, such
	as:</para>

      <programlisting><lineannotation>&hellip;</lineannotation>
("\\.lsp$" . lisp-mode)
("\\.wiz$" . whizbang-mode)
("\\.scm$" . scheme-mode)
<lineannotation>&hellip;</lineannotation></programlisting>

      <para>This means that Emacs will automatically go into
	<function>whizbang-mode</function> when you edit a file ending
	in <filename>.wiz</filename>.</para>

      <para>Just below this, you will find the
	<symbol>font-lock-auto-mode-list</symbol> entry.  Add
	<function>whizbang-mode</function> to it like so:</para>

      <programlisting>;; Auto font lock mode
(defvar font-lock-auto-mode-list
  (list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'whizbang-mode 'lisp-mode 'perl-mode 'scheme-mode)
  "List of modes to always start in font-lock-mode")</programlisting>

      <para>This means that Emacs will always enable
	<function>font-lock-mode</function> (ie syntax highlighting)
	when editing a <filename>.wiz</filename> file.</para>

      <para>And that is all that is needed.  If there is anything else
	you want done automatically when you open up a
	<filename>.wiz</filename> file, you can add a
	<function>whizbang-mode hook</function> (see
	<function>my-scheme-mode-hook</function> for a simple example
	that adds <function>auto-indent</function>).</para>
    </sect2>
  </sect1>

  <sect1 xml:id="tools-reading">
    <title>Further Reading</title>

    <para>For information about setting up a development environment
      for contributing fixes to FreeBSD itself, please see
      &man.development.7;.</para>

    <itemizedlist>
      <listitem>
	<para>Brian Harvey and Matthew Wright
	  <emphasis>Simply Scheme</emphasis>
	  MIT 1994.<!-- <br> -->
	  ISBN 0-262-08226-8</para>
      </listitem>

      <listitem>
	<para>Randall Schwartz
	  <emphasis>Learning Perl</emphasis>
	  O'Reilly 1993<!-- <br> -->
	  ISBN 1-56592-042-2</para>
      </listitem>

      <listitem>
	<para>Patrick Henry Winston and Berthold Klaus Paul Horn
	  <emphasis>Lisp (3rd Edition)</emphasis>
	  Addison-Wesley 1989<!-- <br> -->
	  ISBN 0-201-08319-1</para>
      </listitem>

      <listitem>
	<para>Brian W. Kernighan and Rob Pike
	  <emphasis>The Unix Programming Environment</emphasis>
	  Prentice-Hall 1984<!-- <br> -->
	  ISBN 0-13-937681-X</para>
      </listitem>

      <listitem>
	<para>Brian W. Kernighan and Dennis M. Ritchie
	  <emphasis>The C Programming Language (2nd Edition)</emphasis>
	  Prentice-Hall 1988<!-- <br> -->
	  ISBN 0-13-110362-8</para>
      </listitem>

      <listitem>
	<para>Bjarne Stroustrup
	<emphasis>The C++ Programming Language</emphasis>
	Addison-Wesley 1991<!-- <br> -->
	ISBN 0-201-53992-6</para>
      </listitem>

      <listitem>
	<para>W. Richard Stevens
	  <emphasis>Advanced Programming in the Unix Environment</emphasis>
	  Addison-Wesley 1992<!-- <br> -->
	  ISBN 0-201-56317-7</para>
      </listitem>

      <listitem>
	<para>W. Richard Stevens
	  <emphasis>Unix Network Programming</emphasis>
	  Prentice-Hall 1990<!-- <br> -->
	  ISBN 0-13-949876-1</para>
      </listitem>
    </itemizedlist>
  </sect1>

</chapter>